2016-05-17 3 views
1

Скажем, у меня есть два класса:Как я могу ссылаться на переменную дочернего класса из метода унаследованного родительского класса в PHP?

class ParentClass 
{ 
    public function getSomething() 
    { 
     return $this->variable_name; 
    } 
} 

class ChildClass extends ParentClass 
{ 
    private $variable_name = 'something specific to child class'; 
    ... 
} 

Тогда я вызываю код для конкретизации ChildClass и вызвать унаследованный getSomething() метод:

$object = new ChildClass(); 
$value = $object->getSomething(); 

Когда я звоню, что последней строки, он дает мне ошибку, потому что $variable_name не существует в ParentClass. Я ожидаю, что ChildClass наследует метод getSomething(), но я понимаю, что, поскольку он не переопределяется явно в ChildClass, он использует область родителя при запуске родительской версии метода.

Как наиболее эффективно иметь ChildClass наследует метод и дать ему возможность читать $variable_name, когда указанный метод называется классом ребенка?

+3

Просто сделайте его защищенным, а не частным. Частный означает, что он принадлежит к этому классу и только к этому классу (без наследования): https://eval.in/572905 vs https://eval.in/572906 –

+0

Что делать, если какой-либо дочерний класс не имеет этой переменной? какой родитель должен делать? –

+0

Конечно, я бы проверил наличие переменной. И спасибо за комментарий, Робби. Я полностью пропустил это. – TerranRich

ответ

0

Короткий ответ: вы не можете.

Длинный ответ: Это не так, как работает OO. Родительские классы не знают ваших детей. Что вы можете сделать, это использовать Reflection, но это не путь, вам нужно переосмыслить свой проект.

class Parent { 
    public function getSomething(Child $child) { 
     $reflection = new ReflectionObject($child); 
     $variable_name = $r->getProperty('variable_name'); 
     $variable_name->setAccessible(true); 
     return $variable_name->getValue($child); 
    } 
} 
3

правило: если ваш родительский класс должен знать что-либо о дочерних классов, то вы делаете что-то неправильно.

При проектировании классов или интерфейсов вы должны сначала подумать о actions (методах), которые они могут выполнять. Не думайте о своих internal state (переменные).

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

Для различных состояний, можно реализовать что-то вроде этого:

class ParentClass { 
    private $variable; 
    function __construct($var) { 
     $this->variable = $var; 
    } 
    function getSomething() { 
     return $this->variable; 
    } 
} 
class ChildClass extends ParentClass { 
    function __construct() { 
     parent::__construct('something specific to child class'); 
    } 
} 

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

другой подход, чтобы сделать контракт:

abstract class ParentClass { 
    function getSomething() { 
     return $this->internalGetSomething(); 
    } 
    abstract function internalGetSomething(); 
} 
class ChildClass extends ParentClass { 
    function internalGetSomething() { 
     return 'something specific to child class'; 
    } 
} 

так, internalGetSomething является договор между родителем и ребенком

+0

Я не согласен с этим утверждением. Второй пример, а также использование интерфейсов у детей - прекрасный пример того, где родители будут точно знать, что будут делать детские классы. Согласованный, он не должен обращаться к свойствам, а скорее к методам –

+0

@ robbie-averill no, parent объявляет контракт, за которым должны следовать дети. Вероятно, этот конкретный пример не очень хорошо иллюстрирует концепцию. Но здесь у нас есть конкретный вопрос –

0

Так же, как Вы сказали, то ChildClass наследует от ParentClass, а не наоборот. Для ParentClass $this->variable_name является неизвестной переменной. Простым способом, который я бы предложил, было бы немного изменить метод ParentClass и переопределить его в ChildClass как таковой:

class ParentClass 
{ 
    public function getSomething($param) 
    { 
     return $param; 
    } 
} 

class ChildClass extends ParentClass 
{ 
    private $variable_name = 'something specific to child class'; 

    public function getSomething($param = "") 
    { 
     return parent::getSomething($param = $this->variable_name); 
    } 
} 

$object = new ChildClass(); 
$value = $object->getSomething(); 
echo $value; 
Смежные вопросы