Я работаю над фреймворком, который стараюсь печатать как можно сильнее. (Я работаю в PHP и беру некоторые идеи, которые мне нравятся, из C# и пытаюсь использовать их в этой среде.) Я создаю класс 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
в выражении. Добавление круглых скобок вокруг переменной 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
.
protected
, ее все еще можно изменить в коде. При этом нет никакой реальной безопасности, поскольку переменная$type
не будет изменена случайно. На что я надеялся, так это на страховку от этого. - person Nathan Loding   schedule 09.06.2010