2012-10-29 86 views
6

到目前爲止,我覺得我已經理解了OOP編程的概念和優點,並且我對於理解如何使用PHP中的類沒有任何困難。在另一個類中傳遞整個類作爲參數

但是,這讓我只是有點困惑。我想我可能會理解,但我仍然不確定。

我一直在下面一組視頻教程(不知道在規則上鍊接到外部資源,但我發現他們在YouTube上),他們是非常自我解釋。除了令人沮喪的是,當導師決定在另一個班級中通過一個班級作爲參數時。至少我認爲這就是發生了什麼;

Class Game 
{ 

    public function __construct() 
    { 
     echo 'Game Started.<br />'; 
    } 
    public function createPlayer($name) 
    { 
     $this->player= New Player($this, $name); 
    } 
} 


Class Player 
{ 

    private $_name; 

    public function __construct(Game $g, $name) 
    { 
     $this->_name = $name; 
     echo "Player {$this->_name} was created.<br />"; 
    } 
} 

然後我實例化一個Game類的對象並調用它的方法;

$game = new Game(); 
$game-> createPlayer('new player'); 

而令人沮喪的,導師並沒有真正解釋爲什麼他已經做到了這一點,並沒有顯示出來,據我所看到的,這將證明它的代碼的任何電話。

Player是否作爲參考傳入Game類中的魔術方法構造函數?這是否意味着整個類可以通過引用在Player類中訪問?當引用$ this而不指向任何特定的方法或屬性時,是否引用了整個類?

如果這是正在發生的事情,那我爲什麼要這樣做呢?如果我在我的遊戲類中創建了一個玩家,那麼我當然可以在遊戲類中訪問我的玩家屬性和方法,對吧?爲什麼我要在我的Player類中使用我的Game類?那麼我可以在Player類中調用createPlayer()嗎?

我道歉,如果我的解釋是,在所有的混亂。

我想我的問題歸結爲;什麼是我完全作爲參數傳遞的,爲什麼我想在每天的OOP編程中做到這一點?

+1

在某些時候,他必須做出'Player'類中使用變量'$ g'的。構造函數中的Game這個詞是[類型提示](http://php.net/manual/en/language.oop5.typehinting.php),它強制只有該類參數中傳遞了類「Game」的對象。其他任何東西都會拋出異常。 –

+0

添加'Class Player extends Game'是否更合乎邏輯?我不是PHP專家,但爲什麼這樣做? –

+1

@AngeloA'Player'沒有擴展'Game',而是'Game'是'Player'的依賴。在'Player'構造函數中,'Game'的公共API將通過'$ g'變量可用 – Phil

回答

4

這就是所謂的type hinting和他沒有通過整個類作爲參數,但ratter暗示的級球員有關的第一個參數

PHP 5的類型介紹類型提示。函數現在是能夠迫使參數是對象(通過在函數原型指定類的名稱),接口,數組(自PHP 5.1)或可調用(自PHP 5.4)。但是,如果將NULL用作默認參數值,則它將被允許作爲任何稍後調用的參數。

(從PHP手冊中提取)

這是否意味着整個類是引用Player類中訪問?

不是整個類,但你可以訪問你作爲參數傳遞

+0

這很簡單地回答了我的問題。謝謝。我仍然沒有100%清楚我可以對類實例的引用做些什麼。我可以使用print_r將其回顯出來,但我不知道如何訪問任何對象的屬性。 –

2
/** 
* Game class. 
*/ 
class Game implements Countable { 
    /** 
    * Collect players here. 
    * 
    * @var array 
    */ 
    private $players = array(); 

    /** 
    * Signal Game start. 
    * 
    */ 
    public function __construct(){ 
     echo 'Game Started.<br />'; 
    } 

    /** 
    * Allow count($this) to work on the Game object. 
    * 
    * @return integer 
    */ 
    public function Count(){ 
     return count($this->players); 
    } 

    /** 
    * Create a player named $name. 
    * $name must be a non-empty trimmed string. 
    * 
    * @param string $name 
    * @return Player 
    */ 
    public function CreatePlayer($name){ 
     // Validate here too, to prevent creation if $name is not valid 
     if(!is_string($name) or !strlen($name = trim($name))){ 
      trigger_error('$name must be a non-empty trimmed string.', E_USER_WARNING); 
      return false; 
     } 
     // Number $name is also not valid 
     if(is_numeric($name)){ 
      trigger_error('$name must not be a number.', E_USER_WARNING); 
      return false; 
     } 
     // Check if player already exists by $name (and return it, why create a new one?) 
     if(isset($this->players[$name])){ 
      trigger_error("Player named '{$Name}' already exists.", E_USER_NOTICE); 
      return $this->players[$name]; 
     } 
     // Try to create... this should not except but it's educational 
     try { 
      return $this->players[$name] = new Player($this, $name); 
     } catch(Exception $Exception){ 
      // Signal exception 
      trigger_error($Exception->getMessage(), E_USER_WARNING); 
     } 
     // Return explicit null here to show things went awry 
     return null; 
    } 

    /** 
    * List Players in this game. 
    * 
    * @return array 
    */ 
    public function GetPlayers(){ 
     return $this->players; 
    } 

    /** 
    * List Players in this game. 
    * 
    * @return array 
    */ 
    public function GetPlayerNames(){ 
     return array_keys($this->players); 
    } 
} // class Game; 


/** 
* Player class. 
*/ 
class Player{ 
    /** 
    * Stores the Player's name. 
    * 
    * @var string 
    */ 
    private $name = null; 

    /** 
    * Stores the related Game object. 
    * This allows players to point to Games. 
    * And Games can point to Players using the Game->players array(). 
    * 
    * @var Game 
    */ 
    private $game = null; 

    /** 
    * Instantiate a Player assigned to a Game bearing a $name. 
    * $game argument is type-hinted and PHP makes sure, at compile time, that you provide a proper object. 
    * This is compile time argument validation, compared to run-time validations I do in the code. 
    * 
    * @param Game $game 
    * @param string $name 
    * @return Player 
    */ 
    public function __construct(Game $game, $name){ 
     // Prevent object creation in case $name is not a string or is empty 
     if(!is_string($name) or !strlen($name = trim($name))){ 
      throw new InvalidArgumentException('$name must be a non-empty trimmed string.'); 
     } 
     // Prevent object creation in case $name is a number 
     if(is_numeric($name)){ 
      throw new InvalidArgumentException('$name must not be a number.'); 
     } 
     // Attach internal variables that store the name and Game 
     $this->name = $name; 
     $this->game = $game; 
     // Signal success 
     echo "Player '{$this->name}' was created.<br />"; 
    } 

    /** 
    * Allow strval($this) to return the Player name. 
    * 
    * @return string 
    */ 
    public function __toString(){ 
     return $this->name; 
    } 

    /** 
    * Reference back to Game. 
    * 
    * @return Game 
    */ 
    public function GetGame(){ 
     return $this->game; 
    } 

    /** 
    * Allow easy access to private variable $name. 
    * 
    * @return string 
    */ 
    public function GetName(){ 
     return $this->name; 
    } 
} // class Player; 

// Testing (follow main comment to understand this) 
$game = new Game(); 
$player1 = $game->CreatePlayer('player 1'); 
$player2 = $game->CreatePlayer('player 2'); 
var_dump(count($game)); // number of players 
var_dump($game->GetPlayerNames()); // names of players 

重寫了代碼在一個更好的方式類的實例,並添加了一些所做的代碼所缺少變量毫無意義:

  • 在玩家類別中,您不存儲遊戲。
  • 在遊戲課程中,您只支持一名玩家。
  • 沒有錯誤檢查...任何地方。

固定所有這些加:

  • 添加例外(防止對象的創建)
  • Try{} catch(...){}異常處理任何OOP開發應該知道
  • 實現可計算的接口,允許計數($遊戲)玩家
  • 一些更多的技巧,會給你一個很好的閱讀

請按照評論,我希望你的代碼在閱讀後會更有意義。

+1

感謝您爲重新編寫代碼所做的努力。我一定會在我的IDE中試用它,並試着理解它所做的一切。OOP對我來說仍然有點令人生畏,做了很長時間的程序,但結構上我發現它更具可擴展性。再次感謝。 –

3

的方法並期望得到一個對象,它是Game別的的一個實例,它會報錯了。

你只是路過這裏的Game一個實例:New Player($this, $name);關鍵的詞$this指對象實例你在

而在去年....我(和其他人對這個問題)有任何想法。作者爲什麼這樣做,因爲他在通過它之後沒有使用該實例。

爲什麼你會傳遞一個類的實例?
想象一個接受用戶作爲輸入的類,並且根據某些邏輯對他們做些什麼。 (在代碼中沒有意見,因爲函數名和類名應該是不言自明)

class User{ 
    protected $name,$emp_type,$emp_id; 
    protected $department; 

    public function __construct($name,$emp_type,$emp_id){ 
    $this->name = $name; 
    $this->emp_type = $emp_type; 
    $this->emp_id = $emp_id; 
    } 

    public function getEmpType(){ 
    return $this->emp_type; 
    } 

    public function setDep($dep){ 
    $this->department = $dep; 
    } 
} 


class UserHub{ 

    public function putUserInRightDepartment(User $MyUser){ 
     switch($MyUser->getEmpType()){ 
      case('tech'): 
       $MyUser->setDep('tech control'); 
       break; 
      case('recept'): 
       $MyUser->setDep('clercks'); 
       break; 
      default: 
       $MyUser->setDep('waiting HR'); 
       break; 
     } 
    } 
} 

$many_users = array(
    0=>new User('bobo','tech',2847),  
    1=>new User('baba','recept',4443), many more 
} 

$Hub = new UserHub; 
foreach($many_users as $AUser){ 
    $Hub->putUserInRightDepartment($AUser); 
} 
相關問題