Я родом из мира .NET. Теперь войдите в эти фригидные воды.
Я нашел пример, который немного озадачил меня. Конечно, я пытаюсь применить основы ООП к этому php-коду, но это не имеет смысла.
Это класс, о котором я говорю.
<?php namespace app\models; class User extends \yii\base\Object implements \yii\web\IdentityInterface { public $id; public $username; public $password; public $authKey; private static $users = [ '100' => [ 'id' => '100', 'username' => 'admin', 'password' => 'admin', 'authKey' => 'test100key', ], '101' => [ 'id' => '101', 'username' => 'demo', 'password' => 'demo', 'authKey' => 'test101key', ], ]; public static function findIdentity($id) { return isset(self::$users[$id]) ? new static(self::$users[$id]) : null; } public static function findByUsername($username) { foreach (self::$users as $user) { if (strcasecmp($user['username'], $username) === 0) { return new static($user); } } return null; } public function getId() { return $this->id; } public function getAuthKey() { return $this->authKey; } public function validateAuthKey($authKey) { return $this->authKey === $authKey; } public function validatePassword($password) { return $this->password === $password; } }
Хорошо, для меня очевидно, что в методе findByIdentity ($ id) все, что он делает, это создание статического нового экземпляра User. Это первое, что меня насторожило.
В .net вы не можете создать экземпляр статического класса.
Теперь, двигаясь дальше. в этой строке
return isset(self::$users[$id])? new static(self::$users[$id]) : null;
второе, что меня интригует, следующее.
Поскольку все, что у вас есть в этом массиве, – это набор ключей / значений ….
private static $users = [ '100' => [ 'id' => '100', 'username' => 'admin', 'password' => 'admin', 'authKey' => 'test100key', ], '101' => [ 'id' => '101', 'username' => 'demo', 'password' => 'demo', 'authKey' => 'test101key', ], ];
как php определяет, что он должен создать объект User? Отражение? Это приводит меня к следующему вопросу … глядя на класс, который он наследует от Object в конструкторе, есть один параметр, который является массивом (одним из элементов массива выше).
public function __construct($config = []) { if (!empty($config)) { Yii::configure($this, $config); } $this->init(); }
НО, этот класс в своем конструкторе вызывает Yii :: configure ($ this, $ config), и в этом методе, как я его вижу, Yii добавляет к $ this (экземпляр объекта, который я предполагаю, а не пользовательский ) параметры, которые принадлежат пользователю.
public static function configure($object, $properties) { foreach ($properties as $name => $value) { $object->$name = $value; } return $object; }
Мне кажется, что это динамически добавляет параметры к объекту, который будет доступен пользователю через соответствующие параметры.
Имеет смысл?
С точки зрения моего .net, $ this в Object ссылается на экземпляр Object, а не на экземпляр пользователя, наследующий его (как говорит мой друг). Я сказал ему, что это нарушение основных принципов ООП, и это просто невозможно.
Кто-нибудь, кто может заставить меня понять об этом?
Спасибо.
Для всех, кого это интересует, вот хороший ответ с длинным объяснением.
Наслаждайтесь!
В PHP нет такого понятия, как статический класс, в нем могут быть статические методы и статические члены. Но каждый класс может быть создан. Однако вы можете использовать исключение в конструкторе.
Теперь … по ключевому слову static. В контексте, который вы используете, он вызывает конструктор позднего статически связанного класса. Вот код, который поможет вам.
class Something { public static function getInstance() { return new static(); } } class Other extends Something { }
Когда вы вызываете getInstance
из контекста Other
, то, что getInstance
делает, вызывает конструктор для класса Other
// this will print `Other` echo get_class(Other::getInstance());
Кроме того, поскольку вы наследуете из класса yii\base\Object
и вы не определяете конструктор в User
, вызывающий конструктор является тем, который вызывается в yii\base\Object
Теперь во вторую часть вашего вопроса
С точки зрения моего .net, $ this в Object ссылается на экземпляр Object, а не на экземпляр пользователя, наследующий его (как говорит мой друг). Я сказал ему, что это нарушение основных принципов ООП, и это просто невозможно.
$ this ссылается на фактический объект, независимо от класса, из которого был создан объект. Вы можете сделать это и в .NET, хотя вам нужно будет отбросить ваш объект. Но для PHP, где нет сильной типизации, объект представляет себя как есть, и вы можете использовать его как есть.