В PHP есть странная особенность - видимость защищённых свойств и методов вне созданного объекта. Пример: Код (Text): class A { protected $protected = 'Bug!'; } class B extends A { public function __construct() { $obj = new A; var_dump($obj->protected); } } Чем руководствовались разработчики ПХП, не понятно. Но я считаю, что это баг, который возвели в ранг особенности. И этот баг напрягает регулярно. ... Может я ретроград? Может я что-то пропустил и за последние 10 лет видимость защищённых свойств вне объекта стало нормой?
Наследование влияет на результат. https://secure.php.net/manual/ru/language.oop5.visibility.php#language.oop5.visibility-other-objects
Из наследника - нормально. Насколько помню, и в плюсах так же. Вот приватные из наследника не видны ни в каком виде (кроме рефлексии)
Естественно, нормально. Так у всех. А из вне объекта нормально? (я именно об этом) --- Добавлено --- Например, из логики видимости. Protected д.б. видим только в объекте и его наследниках. Интересно, вообще есть ещё какие-нибудь языки, где защищённый доступен из вне объекта?
Нормально, если внутри метода наследника. Приватные свойства других экземпляров того же класса тоже видно из методов (но уже не наследника). Тут инкапсуляция не нарушается, всё ОК, свой сор наружу не выносим
Он не о том. Он не ожидал, что экземпляр класса-предка, созданный внутри потомка, будет предоставлять потомку протектеды. Потому что по логике вещей, протектед - это когда класс-потомок наследует свойства и методы предка, к которым нет доступа извне. Но не когда эти свойства и методы видны и у экземпляров предка.
Не то, что не ожидал, - я знаю про эту особенность давно. Просто это неправильно, по логике ООП. Долго мучался и в конце концов решил выяснить, что думают профи по этому поводу.
Подозреваю, что так исторически сложилось: сначала ошиблись, потом решили что это не критично, а по другому будет тормозить сильнее.
Они руководствовались здравым смыслом и теорией ООП, а именно (Protected (or class-protected) allows the class itself and all its subclasses to access the member). То что потомок может наследовать(переопределять по сути) протектед свойства - это одно, а область видимости(потомок видит и обращается к протектед или паблик свойству предка) это несколько другое. Где тут баг? Где написано что должно быть подругому? Это всегда было нормой. Просто видимо ты изначально неправильно понял этот момент. Такое поведение не только в Php, но и например в Java. Надеюсь никто не будет тут говорить что Java недостаточно или неправильно имплементирует ООП?
А как тогда писать методы, сравнивающие два состояния? Ну в C++ такие штуки используются ещё при перегрузке операторов/конструкторе копирования и т.п. В php вместо конструктора копирования clone, которая работает совсем по-другому, ОК. Но всё ещё остаются операции сравнения. Теоретически, может быть поле, которое светить геттером нет смысла, но при сравнении с другим объектом, к примеру, хотелось бы иметь возможность получить. И с существующей системой всё в порядке: метод класса А может получить доступ к приватным и защищённым свойствам любого экземпляра класса А. А с протектед - ещё и экземпляра родителя. Не вижу здесь нарушения принципа инкапсуляции, поскольку всё это происходит внутри объектов класса a
это проблема. Большинство почему-то считает что это доступ в рамках инстанции, хотя нигде в документации такой оговорки нет. Или где-то есть? Что именно почитать? Это поведение наблюдается во всех ЯП со взрослым ООП. Потомок, в данном случае, является имплементацией двух классов. И родительского и лично своего. instanceof в помощь. Нельзя наследовать свойства не имея к ним доступ, а раз доступ есть, то он есть и внутри инстанции и снаружи. почему вдруг снаружи надо этот доступ ограничить? это ведь тотже самый класс, ибо наследник ТОЧНО знает, что у класса родителя есть это свойство(или метод), и что оно из себя представляет, как реализовано...
А при чём тут "знает"? Protected это видимость (т.е. доступность) свойства или метода объекта, а не знание его структуры. Правильный подход: private: доступно в объекте protected: доступно в объекте и его потомках public: доступно везде, - в объекте, в его потомках, во внешнем мире (относительно объекта)
еще раз... сложно придумать аналогию из физического мира, в данном случае, но я попробую объяснить смысл, которым руководствовались при описании и реализации защищенных свойств(ну и методов) в ООП: PROTECTED это предоставление доступа не только в рамках наследования, но и в рамках прямого доступа по ссылке(это Доступность свойства ВО ВСЕЙ иерархии классов потомков). те Родитель говорит, это поле будет доступно моим наследникам ТАКЖЕ КАК И МНЕ. оно недоступно чужим, но своим без проблем, хоть в рамках наследования, хоть в рамках прямого доступа. те родитель пускает к нему всех потомком и изнутри методов и из вне. а как не пустить? это же любимые дети) как им откажешь.
Niet. Из этой логики вытекает, что приватные свойства открыты всем объектам одного класса. PHP: class A { private $private; public function set($s) { $this->private = $s; } function bingo($o) { echo $o->private; } } $o1 = new A; $o1->set('Vasya'); $o2 = new A; $o2->bingo($o1);
Ты путаешь понятия "класс" и понятие "объект". В твоём случае, $o1 и $o2 это разные объекты. Соответственно, свойства разные (два объекта - два свойства). И неважно, что описание (декларация) структуры объектов одна и та же.
Во всех ОО языках, с которыми я знаком в разной степени (Object Pascal, C++, Java, PHP) методам класса А доступны приватные свойства ЛЮБОГО экземпляра класса А, не только this. Почему тебя это так смущает?
(R) Повторюсь ещё раз... Правильный подход: private: доступно в объекте Только в объекте. И нигде, кроме этого объекта, - на то он и есть "приватный". У разрабов ПХП другая идеология, - они оперируют классами, а не объектами, судя по этому. А это в корне не верно, ибо class это просто описание, декларация, "тип" (аналогично "array"), не более того. Я так считал, считаю и вероятно буду считать, если не переубедюсь. Поэтому и спросил "Может я ретроград?" ... и стал ожидать убедительных доводов ЗА. Пока не очень. п.с. Надеюсь, мы говорим об одном и том же, об ООП, а не о КОП. п.п.с. Когда я узнал об этой "особенности" ПХП, он тут же упал на несколько процентов ближе к плинтусу в моих глазах. И вот mkramer говорит, что Object Pascal, C++, Java имеют туже хрень - и они упали. Куда катится мир... --- Добавлено --- Потому что это неправильно, по моему скромному мнению. п.с. И хочу переубедиться, если я неправ.
Это не правильный подход. То, что ты так хочешь, не делает это правильным. С тем же успехом можно говорить, что правильный подход - это кушать задницей. А те, кто кушают ртом, просто не понимают цимес и заблуждаются. Грубенько вышло, но суть примерно та же. --- Добавлено --- дык ты их не читаешь, судя по всему --- Добавлено --- Это не иначе как массонский заговор. Лично против тебя.