到目前为止,我觉得我已经理解了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 Class?那么,我可以在Player类中调用createPlayer()吗?
如果我的解释一直令人困惑,我道歉。
我想我的问题归结为;什么是我作为参数完全传递,为什么我想在每天的OOP编程中做到这一点?
答案 0 :(得分:4)
它被称为type hinting并且他没有将整个类作为参数传递,而是在暗示类播放器关于第一个参数的类型
PHP 5引入了类型提示。函数现在能够强制参数为对象(通过在函数原型中指定类的名称),接口,数组(自PHP 5.1起)或可调用(自PHP 5.4起)。但是,如果将NULL用作默认参数值,则允许将其作为后续调用的参数。
(摘自php手册)
这是否意味着可以通过引用在Player类中访问整个类?
不是整个类,但您可以访问作为参数传递的类的实例
答案 1 :(得分:3)
该方法期望获得一个对象,该对象是Game
的任何其他实例,并且它将会出错。
您正在此处传递Game
的实例:New Player($this, $name);
关键字$this
指的是您所在的对象实例。
最后......我(也没有其他任何人)知道作者为什么这样做,因为他在通过它后没有使用Game
实例。
为什么你要通过一个班级的实例?
想象一个接受用户作为输入的类,并根据某些逻辑对它们做一些事情。 (代码中没有注释,因为函数名和类名应该是不言自明的)
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);
}
答案 2 :(得分: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开发的异常应该知道按照评论进行操作,我希望您的代码在阅读后更有意义。