Прежде всего: довольно похожая проблема была опубликована и как-то решена уже, но по-прежнему не отвечает на мою конкретную проблему. Подробнее об этом позже.
В словах: у меня есть базовый класс, который предоставляет некоторые методы для всех дочерних элементов, но не содержит никакого свойства. Мой ребенок наследует эти методы, которые должны использоваться для доступа к свойствам дочернего элемента. Если свойство дочернего объекта protected
или public
, все работает нормально, но если свойство дочернего объекта является private
, оно не выполняется без ошибок (просто ничего не происходит).
В коде:
class MyBaseClass { public function __set($name, $value) { if(!property_exists($this, $name)) throw new Exception("Property '$name' does not exist!"); $this->$name = $value; } } class ChildClass extends MyBaseClass { public $publicProperty; protected $protectedProperty; private $privateProperty; } $myChild = new ChildClass(); $myChild->publicProperty = 'hello world'; //works of course! $myChild->protectedProperty = 'hello world'; //works as expected $myChild->privateProperty = 'hello world'; //doesn't work?
Вышеупомянутая подобная проблема получила решение использовать магический __set()
для доступа к приватным свойствам, но это я уже делаю. Если я реализую __set()
внутри дочернего элемента, это работает, конечно, но идея состоит в том, что ребенок наследует __set()
от его родителя, но, очевидно, он не может получить доступ к частному методу ребенка.
Это специально? Я что-то делаю неправильно? или мой подход просто дерьмо по дизайну?
Предыстория: Моя оригинальная идея: вся динамическая вещь о __set()
– это то, что мне не нравится. Обычно частная собственность никогда не должна быть доступна извне, поэтому я реализовал металирование __set- и __get-методов в моем конечном базовом классе (из которого наследуются все классы).
Теперь я хочу динамически порождать экземпляр из файла XML и, следовательно, нуждаться в доступе к свойствам. Я сделал правило, что любой XML-экземплярный класс должен реализовать магический __set()
и поэтому может быть создан динамически. Вместо того, чтобы внедрять его в каждый класс, который может быть порожден однажды, я решил наследовать их из класса под названием class Spawnable { }
который предоставляет необходимый метод __set.
В этом разница между private
и protected
. Частные методы и свойства не могут быть унаследованы или достигнуты. Вам нужно будет заменить их на защищенные.
См. Руководство по видимости
Доступ к элементам, объявленным защищенными, может быть доступен только внутри самого класса и наследуемых и родительских классов. Участникам, объявленным как private, может быть доступен только класс, определяющий участника.
Думаю, вы могли бы что-то использовать с помощью Reflection. Например, в вашем классе Spawnable:
public function __set($name, $value) { $reflector = new ReflectionClass(get_class($this)); $prop = $reflector->getProperty($name); $prop->setAccessible(true); $prop->setValue($this, $value); }
Однако не самый красивый код.
Рассмотрев мою концепцию, я думаю, что это плохая идея, чтобы пойти с этим подходом. Это общая проблема с отсутствием различий между свойствами и полями PHP. Конечно, частные поля никогда не должны быть доступны извне, а только свойства, которые определяются программистом. Отсутствие авто-свойств (и я не имею в виду эти магические методы __set()
и __get()
) или некоторые обычные правила доступа к свойствам, затрудняет угадать, какое соглашение об именах было использовано программистом при реализации сеттеров для частных полей в своем классе.
Лучшая концепция здесь может заключаться в том, чтобы полагаться на существование хорошо названных сеттеров для каждого нерегулярного класса, хотя это может сломаться, если кто-то внес свой код, который не реализует ожидаемые обычные именованные сеттеры.
Однако большое спасибо за ваши мысли и подсказки!