Магические методы (__get, __set) не работают в расширенном классе?

<?php abstract class AbstractClass { public function __get($theName) { return (isset($this->$theName)) ? $this->$theName : NULL; } public function __set($theName, $theValue) { if (false === property_exists(get_class(), $theName)) { throw new Exception(get_class()." does not have '".$theName."' property."); } else { $this->$theName = $theValue; } } } class ConcreteClass extends AbstractClass { private $x; private $y; public function __construct($theX, $theY) { $this->x = $theX; $this->y = $theY; } } $concreteClass = new ConcreteClass(10, 20); var_dump( $concreteClass->x ); 

Есть ли способ облегчить эту работу или мне придется добавить эти магические методы в расширенный класс?

Это будет работать:

 public function __get($theName) { if(property_exists($this, $theName)) { $reflection = new ReflectionProperty($this, $theName); $reflection->setAccessible($theName); return $reflection->getValue($this); } } 

IMO, вы не должны использовать __get и __set в качестве замены для __set и __set . Поскольку они срабатывают при попытке доступа к недоступному свойству, они гораздо больше связаны с обработкой ошибок. И они также намного медленнее обычного геттера или сеттера.

Ваша проблема в том, что элементы $ x и $ y, установленные в ConcreteClass являются частными. Поскольку метод __get() определен в родительском классе, он не имеет доступа к закрытым членам дочернего класса (поскольку частные члены доступны только самим классом, а не каким-либо дочерним или родительским классом). Чтобы они были видны родительскому классу, они должны быть либо protected либо public . Для вашего случая вам нужно использовать защищенный для сохранения магической функции вне класса.

Это, однако, в лучшем случае очень странная практика. Если к переменным можно получить доступ с помощью магических методов, в первую очередь их не нужно делать частным.

Это связано с тем, что ваши x и y принадлежат ConcreteClass , а s functions only work for parent parent s functions only work for parent свойств s functions only work for parent . Например, если у вас есть:

 abstract class AbstractClass { private $x; //... } class ConcreteClass extends AbstractClass { private $y; public function __construct($theX, $theY) //... 

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

Обновить

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

Также в качестве альтернативы вы можете скопировать-вставить метод __get из AbstractClass в ConcreteClass, предоставив таким образом родительский доступ к закрытым свойствам своего descedant; но снова «вы можете это сделать» не означает «вы должны это сделать» :).