Унаследованный родительский метод PHP не может получить доступ к частной собственности ребенка - PullRequest
10 голосов
/ 26 октября 2010

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

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

Ответы [ 3 ]

17 голосов
/ 26 октября 2010

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

См. Руководство по видимости

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

4 голосов
/ 26 октября 2010

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

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

Хотя не самый красивый код.

1 голос
/ 28 октября 2010

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

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

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

...