Передача всего класса в качестве параметра в другом классе
до сих пор я чувствую, что понял концепцию и преимущества программирования ООП, и у меня не было никаких трудностей с пониманием того, как работать с классами в 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');
довольно неприятно, что учитель на самом деле не объясняет, почему он это сделал, и, насколько я вижу, не отображал никаких вызовов в коде, которые оправдывали бы это.
является конструктором метода magic в Player прохождение в игровом классе в качестве ссылки? Означает ли это, что весь класс доступен в классе Player по ссылке? При ссылке на $this без указания на какой-либо конкретный метод или свойство вы ссылаетесь на весь класс?
Если это то, что происходит, то зачем мне это делать? Если я создал игрока в своем игровом классе, то, конечно, я могу просто получить доступ к свойствам и методам игрока в игровом классе, верно? Зачем мне мой игровой класс? в моем классе игроков тоже? Могу ли я, например, вызвать createPlayer() в классе Player?
Я извиняюсь, если мое объяснение было вообще запутанным.
Я думаю, что мой вопрос сводится к; ЧТО ЭТО такое, что я передаю как параметр точно, и почему я хочу делать это каждый день программирования ООП?
3 ответов
Это называется введите hinting и он не передает весь класс в качестве параметра, но ratter намекает игроку класса о типе первого параметра
PHP 5 вводит тип hinting. Функции теперь могут заставить параметры быть объектами (путем указания имени класса в прототипе функции), интерфейсами, массивами (начиная с PHP 5.1) или вызываемыми (начиная с PHP 5.4). Однако если NULL используется в качестве значения параметра по умолчанию, это будет разрешено в качестве аргумента для последующего вызова.
(извлечено из руководства php)
означает ли это, что весь класс доступен в классе Player по ссылке?
не весь класс, но вы можете получить доступ к экземпляру класса вы передаете в качестве параметра
метод ожидает получить объект, который является экземпляром Game
что-нибудь еще, и это будет ошибка.
вы проходите экземпляр Game
здесь: New Player($this, $name);
ключевое слово $this
ссылается на экземпляр объекта, в котором вы находитесь.
и последнее....Я (и никто другой, если на то пошло) понятия не имею, почему автор это сделал, так как он не использует Game
экземпляр после его прохождения.
почему бы u передать экземпляр a класс?
Представьте себе класс, который принимает пользователей в качестве входных данных и в соответствии с некоторой логикой что-то с ними делает. (Нет комментариев в коде, так как имя функции и имя класса должны быть понятными)
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);
}
/**
* 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(...){}
обработка исключений любой ООП dev должен знай - реализован Счетный интерфейс, позволяющий считать ($game) игроков
- еще несколько трюков, которые дадут вам хорошее чтение
следуйте комментариям, и я надеюсь, что ваш код будет иметь больше смысла после его прочтения.