Я работаю над фреймворком, который я пытаюсь ввести так сильно, насколько это возможно. (Я работаю в PHP и беру некоторые из идей, которые мне нравятся на C#, и пытаюсь использовать их в этой структуре.) Я создаю класс Collection, который представляет собой совокупность объектов/объектов домена. Это похоже на модель List<T>
в .Net.PHP 'instanceof' с ошибкой класса
Я столкнулся с препятствием, которое мешает мне печатать этот класс. Если у меня есть UserCollection, он должен включать только объекты User. Если у меня есть PostCollection, он должен разрешать только объекты Post.
Все коллекции в этой структуре должны иметь определенные базовые функции, такие как добавление, удаление, итерация. Я создал интерфейс, но обнаружил, что не мог сделать следующее:
interface ICollection { public function add($obj) }
class PostCollection implements ICollection { public function add(Post $obj) {} }
Это нарушило его соответствие интерфейсу. Но я не могу сильно навязать интерфейс, потому что тогда все коллекции одного типа. Поэтому я попытался следующее:
interface ICollection { public function add($obj) }
abstract class Collection implements ICollection { const type = 'null'; }
class PostCollection extends Collection {
const type = 'Post';
public function add($obj) {
if(!($obj instanceof self::type)) {
throw new UhOhException();
}
}
}
При попытке запустить этот код, я получаю syntax error, unexpected T_STRING, expecting T_VARIABLE or '$'
на instanceof
заявление. Небольшое исследование проблемы, и похоже, что причиной этого является то, что $obj instanceof self
действителен для тестирования класса. Похоже, что PHP не обрабатывает весь оператор self::type
в выражении. Добавление скобок вокруг переменной self::type
бросила ошибку относительно неожиданного «(».
Очевидного решения является не сделать переменную type
константы. Выражение $obj instanceof $this->type
работает нормально (если $type
объявлен как переменные, конечно).
Я надеюсь, что есть способ избежать этого, поскольку я хотел бы определить значение как константу, чтобы избежать любых возможных изменений в переменной позже. Любые мысли о том, как я могу это достичь, или есть ли способ «ускользнуть» или инкапсулировать self::this
, чтобы PHP не умирал при его обработке?
ОБНОВЛЕНИЕ Основываясь на обратной связи ниже, я подумал о чем-то попробовать - код ниже работает! Может ли кто-нибудь подумать о 1) причине не делать этого, 2) причина, по которой это не будет в конечном счете работать, или 3) лучший способ снять это?
interface ICollection { public function add($obj) }
abstract class Collection { const type = null; protected $type = self::type; }
class PostCollection extends Collection {
const type = 'Post';
public function add($obj) {
if(!($obj instanceof $this->type)) {
throw new UhOhException();
}
}
}
UPDATE # 2: После ввода кода выше в производство, оказывается, что это не работает. Я понятия не имею, как это работает, когда я тестировал его, но он не работает вообще. Думаю, я застрял в использовании переменной protected
.
Я думаю, что я ответил на 1 или 2 - даже если т он переменный 'protected', он все равно может быть изменен в коде. Нет никакой реальной безопасности при этом так, что переменная '$ type' не будет изменена случайно. На что я надеялся, была страховка от этого. –
Если я правильно понимаю, вы даете экземпляру операции строку ($ this-> type), когда она должна быть просто именем класса (см. Http://php.net/manual/en/language.operators.type.php) , Я думаю, вы должны использовать 'is_a', поскольку он ожидает строку, которая является типом $ this->. – gacrux
Не истинное утверждение - посмотрите пример № 5 на странице, с которой вы связались. –