PHP Унаследованный родительский метод не может получить доступ к частной собственности пользователя

Прежде всего: A довольно похожая проблема была опубликована и как-то решена уже, но по-прежнему не отвечает на мою конкретную проблему. Подробнее об этом позже.

В словах: У меня есть базовый класс, который предоставляет некоторые методы для всех дочерних элементов, но не содержит никакого свойства. Мой ребенок наследует эти методы, которые должны использоваться для доступа к дочерним свойствам. Если дочернее свойство 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?

Вышеупомянутая подобная проблема получила решение использовать метод magic __set() для доступа к приватным свойствам, но это я уже делаю. Если я реализую __set() внутри дочернего элемента, это работает, конечно, но идея состоит в том, что ребенок наследует __set() от него родителя, но, очевидно, он не может получить доступ к дочернему частному методу.

Это специально? Я что-то делаю неправильно? или мой подход просто дерьмо по дизайну?

Фон: Моя оригинальная идея: вся динамическая вещь о __set() - это то, что мне не нравится. Обычно частная собственность никогда не должна быть доступна извне, поэтому я реализовал металирование __set- и __get-методов в моем конечном базовом классе (из которого наследуются все классы).

Теперь я хочу динамически создавать экземпляр из файла XML и, следовательно, нуждаться в доступе к свойствам. Я сделал правило, что любой XML-экземплярный класс должен реализовать магический метод __set() и поэтому может быть создан динамически. Вместо того, чтобы внедрять его в каждый класс, который может быть порожден однажды, я решил сделать их наследуемыми от класса с именем вроде class Spawnable { }, который предоставляет необходимый метод __set.

Ответ 1

В этом разница между private и protected. Частные методы и свойства не могут быть унаследованы или достигнуты. Вам нужно будет заменить их на защищенные.

См. руководство о видимости

Участники, объявленные защищенными, могут быть доступ только внутри самого класса и по унаследованным и родительским классам. Члены, объявленные как частные, могут доступ к классу, который определяет член.

Ответ 2

Я думаю, вы могли бы что-то использовать с помощью Reflection. Например, в вашем классе Spawnable:

public function __set($name, $value)
{
    $reflector = new ReflectionClass(get_class($this));
    $prop = $reflector->getProperty($name);
    $prop->setAccessible(true);
    $prop->setValue($this, $value);
}

Не самый красивый код.

Ответ 3

После рассмотрения моей концепции, я думаю, что это плохая идея, чтобы пойти с этим подходом. Это общая проблема с отсутствием различий между свойствами и полями PHP. Конечно, частные поля никогда не должны быть доступны извне, а только свойства, которые определяются программистом. Отсутствие автоматических свойств (и я не имею в виду эти магические методы __set() и __get()) или некоторые обычные правила доступа к свойствам, затрудняет угадать, какое соглашение об именах было использовано программистом при реализации сеттеров для частных полей в своем классе.

Лучшая концепция здесь может заключаться в том, чтобы полагаться на существование хорошо известных наборов для каждого нерекомендуемого класса, хотя это может сломаться, если кто-то внесла код, который не реализует ожидаемые обычные именованные сеттеры.

Однако большое спасибо за ваши мысли и подсказки!