Пару лет назад возникал уже вопрос такой, но практики применения не было и поэтому был забыт: PHP: class A { private $data = []; public function __set($name, $value) { $this->data[$name] = $value; } } class B extends A { protected $b; private $c; public function __construct() { $this->a = 'Несуществующее'; $this->b = 'Защищённое'; $this->c = 'Приватное'; } } var_dump(new B); Выхлоп Код (Text): object(B)[2] protected 'b' => string 'Защищённое' (length=20) private 'c' => string 'Приватное' (length=18) private 'data' (A) => array (size=1) 'a' => string 'Несуществующее' (length=28) Как видим при записи в недоступные (защищённые или приватные) свойства не отработала магия методом __set(), то есть документация подсовывает нам лажу: Код (Text): Метод __set() будет выполнен при записи данных в недоступные (защищённые или приватные) или несуществующие свойства. Я правильно понимаю, что нас обманули и запись производится ТОЛЬКО В НЕСУЩЕСТВУЮЩИЕ? Кто-то пояснит мне убогому, что происходит? ))) p.s. для тех, кто сомневается, то дам оригинал __set() is run when writing data to inaccessible (protected or private) or non-existing properties как видим ИЛИ указывает на то, что защищённые и приватные могут существовать и __set() будет выполнен, но этого не происходит
так написано в документации по методу __set()? если ты о том, что __set() работает по месту проживания в A, то как он при создании экземпляра B отработал на несуществующем свойстве и поместил его в массив, который в A согласно документации туда же должны были улететь приват и протектед
Недоступное свойство - это какое свойство? privat, объявленное в классе и используемое в этом-же классе - доступное. protected, объявленное в родительском классе и используемое в наследнике - доступное. privat, объявленное в родительском классе и используемое в наследнике - недоступное. protected, объявленное в классе и используемое извне классе - недоступное.
всё, догнал меня вот это путало - НЕДОСТУПНОЕ, особенно в этой части: protected, объявленное в родительском классе и используемое в наследнике - доступное так как согласно той же документации - протектед виден РОДИТЕЛЯМ, вот тут я жоска путался спасибо за расклад, всё ок, порешали... --- Добавлено --- @Sail а если протектед объявлено в наследнике, то какое оно по отношению к родителю, доступное?
Согласно документации - protected виден наследникам, а не родителям. Базовый класс ничего не знает о свойствах и методах, объявленных в наследнике. Следовательно, если protected (свойство или метод) объявлен в наследнике - в методах базового класса он недоступен. Спойлер На этот случай есть абстрактные методы, например. Объявляешь в базовом классе абстрактный метод, или базовый класс - реализующим некий интерфейс (не забыть класс объявить абстрактным, если не включать реализацию методов интерфейса) и из других методов базового класса можешь вызывать этот "абстрактный" метод. Вызываться будет реализованный в наследнике, так как создан объект класса-наследника и из него уже можно вызвать методы (protected и public базового класса). Ведь в случае абстрактного базового класса - его экземпляр объекта не создаётся. Этот, реализованный в наследнике метод свободно может обращаться со свойствами, объявленными в этом-же "наследнике" и с доступными (публичными и защищёнными) свойствами и методами базового класса.
@Sail а если объявлено в наследнике, то какое оно по отношению к родителю, доступное? вот поэтому и путаница, потому что официальная документация гласит: Модификатор protected (защищённый) разрешает доступ самому классу, наследующим его классам и родительским классам. Как тебе такой поворот? Почему протектед не улетел в массив родителя по __set() назревает вопрос тогда
Имеется ввиду, что из метода родительского класса можно обратиться к protected-свойству класса-наследника. Но только из экземпляра объекта класса-наследника. PHP: class A { public function foo() { return $this->boo; } } class B extends A { protected $boo = 333; public function getBoo() { return $this->boo; } } $boo = new B(); $foo = $boo->foo(); $zoo = $boo->getBoo(); var_dump($foo, $zoo); --- Добавлено --- Потому что он доступен в объекте, созданном из класса-наследника (B).