Я работаю над фреймворком, который я пытаюсь ввести так сильно, насколько это возможно. (Я работаю в PHP и беру некоторые из идей, которые мне нравятся на С#, и пытаюсь использовать их в этой структуре.) Я создаю класс Collection, который представляет собой совокупность объектов/объектов домена. Он вроде бы моделируется после объекта List<T>
в .Net.
Я столкнулся с препятствием, которое мешает мне печатать этот класс. Если у меня есть 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
constant в выражении. Добавление скобок вокруг переменной self::type
привело к ошибке в отношении неожиданного '('.
Очевидным обходным решением является не превращение переменной type
в константу. Выражение $obj instanceof $this->type
работает просто отлично (если $type
объявлено как переменная, конечно).
Я надеюсь, что есть способ избежать этого, поскольку я хотел бы определить значение как константу, чтобы избежать каких-либо возможных изменений в переменной позже. Любые мысли о том, как я могу это достичь, или я беру PHP на это ограничение в этом отношении? Есть ли способ "экранирования" или инкапсуляции 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();
}
}
}
ОБНОВЛЕНИЕ # 2: После того, как вы добавили код в производство, выясняется, что он не работает. Я понятия не имею, как это работает, когда я тестировал его, но он не работает вообще. Я застрял с использованием переменной protected
, я думаю.