напрямик движек не даст конечно. но можно както так. Код (PHP): class A { private $a = 1; public function get1() { return $this->a; } } class B extends A { public function get2() { return $this->get1(); } } $b = new B; var_dump($b->get2()); // int(1) грязная работа, но суть в том, что в наследнике мы получили значение приватного свойства родителя. понятно что тут использовали паблик метод, но я лично думал что движек заругается как-то. но оказывается можно.
А, ну так это не обращение к приватному полю. Тут логика никак не нарушается. Кто угодно может дернуть get1 у такого объекта и получить переменную. Это, к слову, суть инкапсулированных полей в нормальных ООП-языках, где есть адекватные геттеры и сеттеры. Добавлено спустя 3 минуты 21 секунду: Экие чудные дела творятся! Так скоро и типы аргументов объявлять попросют, чтобы был порядок, и чтобы конвертация проходила по факту вхождения в функцию, а не внутри нее, силами/костылями программера, который трижды об нее убьется.
ну так у наследника то этого свойства КАКБЫ нет. оно не описано в классе наследника. но мы его получили. я понимаю, что логика тут срабатывает корректно. но суть вещей нарушается. мы в наследнике получили ЗНАЧЕНИЕ свойства, которого у него НЕТ. я не говорю что это неправильно, просто не совсем очевидно, и надо иметь это в виду. ибо можно так забыть в наследнике указать свое приватное свойство. а все будет работать без ошибок. хотя в методах будет значение предка. такие ошибки трудно найти, если допустить.
Наследник унаследовал публичный метод get1, который, в данном контексте, является геттером приватного поля. Тут все ок. Обычная инкапсуляция. Именно такие вещи ничего не нарушают и не ломают и работают везде. Добавлено спустя 48 секунд: В таком разрезе да, звучит мерзковатенько. Приду домой, проверю в плюсах или шарпах. На всякий.
В Шарпиках все работает. Что, в принципе, логично, опять же. И да, объект-наследник может содержать в себе "лишние" данные по факту, получается. Добавлено спустя 4 минуты: Забавно, правда, раньше о таких вещах никогда не задумывался, тоже считая, что приватные свойства не наследуются. Оказалось, что наследуются, пусть неявно.
Я на это смотрю, как на то, что объявляя функции и методы приватными, мы запрещаем наследникам их использовать напрямую. Но они всё равно у них есть, естественно. Поскольку, ещё раз повторюсь, должны корректно срабатывать унаследованные, но не переопределённые методы родителя.
А это тут при чем?) И да, в шарпиках нет утиной типизации. Если хочешь использовать объект одного класса как объект другого, при том, что они не родня ни разу, надо прямо указать им, мол (objA as objB).do(); И шарпики скажут - окей, под твою ответственность, я не буду ругаться, но если упадет, давай без выпадов в мою сторону, ок? Добавлено спустя 3 минуты 42 секунды: Скажем так, хочешь безболезненно юзать тот или иной интерфейс у указанного объекта, наследуйся от этого интерфейса. Не можешь наследоваться, юзай "as". Хоть вики и говорит, что в шарпах утиная типизация есть. Добавлено спустя 2 минуты 59 секунд: Кстати, в пхп есть такое понятие как интерфейсы и абстрактные классы?
А спецификация как? Просто пока не нужны были, не озадачивался. А то так-то в пхп и понятие перегрузки есть, и даже понятие инкапсулирующих полей...
ну работает как надо вроде. конролируется реализация, ругается когда нужно. можно назначать несколько интерфейсов классу.. ну и абстрактные классы тоже пашут. глюков и отклонений не встречал на практике. хз
хотя... ) например, PHP класс не может имплементировать несколько интерфейсов содержащих одинаковые методы! Довольно странно, учитывая что интерфейс не содержит реализации, и по сути два интерфейса описывающих одинаковый метод ни чему ни противоречат и не создают никаких неоднозначностей.
Не скажи. Получается две неявные идентичные сигнатуры методов в классе. Вот прописал ты реализацию, а какую из сигнатур ты раскрыл? Определенная логика в таком поведении есть. Это как так называемая проблема ромбовидного наследования, которая бывает в C++, если у потомка есть два предка у которых один общий предок. В итоге в потомке финальном образуется косяк. В зависимости от настроек компилятора это либо компиль-еррор, либо неоднозначность, либо просто фаталка при запуске скомпиленного кода на попытке создания объекта. При наследовании от двух не родственных классов/интерфейсов шанс словить такое, конечно, стремится к нулю. Но, искуственно созданная ситуация показывает, что пыху проще не работать с таким, чем работать хоть как-то. Учитывая среднюю квалификацию пыхпышников, это ок. Крайне ок. Меньше говна будет.
да. но. если сигнатуры у методов идентичные, значит нет никакой неоднозначности, по сути. это ведь интерфейс всего лишь. реализации методов нет. реализуя этот метод у класса, совершенно неважно какой метод интерфейса раскрыт - ибо они идентичные полностью. я именно об этом. ромбовидное наследование это немного не то, мне кажется. ибо тут речь про интерфейсы а не про множественное наследование классов. говорят что в данном случае поведение пыха отличается, как раз, от с++ и явы там(в них такое возможно). завтра на работе проверю.
Есть объект - это, по сути, набор данных. С данными связана область их видимости. Есть наследование классов, но нет наследования объектов, объект содержит в себе данные всей иерархии классов. А оператор дампа структуры данных все это выводит - удивляет, что кого-то это удивляет. Скрытие данных - это по сути механизм реализации соглашений между программистами, он может быть достигнут и без языковых конструкций protected/private, а, например, соглашением наимнования свойств и методов. Добавлено спустя 10 минут 20 секунд: В большинстве случаев если у интерфейсов пересекаются названия методов - то проблема в плохом проектировании интерфейсов. Но если это все же как-то случилось, но верх невежества говорить, что одинаково названные методы _разных_ интерфейсов, хоть и с одинаковой сигнатурой можно как-то реализовать одним методом. Это просто непонимание сути интерфейса.
удивляет не сам факт наследования приватов, а то что в доках об этом четко не сказано. отсюда возникают додумки, неоднозначности и возможно, ожидание другого поведения. Во-первых, расскажи это создателям Java, c++, C# ... они вполне позволяют создавать реализацию метода, описанного в разных интерфейсах но с одинаковыми сигнатурами. Вот невежды какие. Во-вторых, обратимся к вики: т.е. дело не в невежестве, а в том что разработчики сами выбирают реализацию исходя из концепций заложенных в ЯП. В-третьих, ты непонял о чем я. я не говорил что поведение в пхп неправильное или плохое, я лишь сказал что оно отличается от других языков, и от моего личного понимания интерфейсов. И ждал обсуждения и идей - почему в пхп ИМЕННО ТАК реализовали это поведение. Если для тебя всё это очевидно - поделись знаниями, нефиг пальцы гнуть
Интерфейс - это не набор методов. Интерфейс - это контракт описывающий функциональность. Случай, когда у нас объект должен реализовать обязательно два контракта одной и той же функциональности, пришедших из разных вендорных библиотек... ну в общем он исчещающе мал, хватит и одного контракта. А если одинаковые сигнатуры, но контракты описывают разоное, то во-перых, это косяк проектировщика интерфейса, а во-вторых, объект вообще не должен реализовывать два разных функционала, хотя бы из SRP. Добавлено спустя 3 минуты: Там как раз позволяют создать разные реализации такого метода. Это может быть полезно, да, когда пришли два плохо спроектировнных интерфейса. Но все-равно, необходимость этого бывает редко. А если язык позволяет тупо определелить реализацию одного метода двех контрактов... ничего хорошего в этом нет, в общем Добавлено спустя 2 минуты: Потому-что с точки зрения работы программиста с объектом - они не наследуются. А внутреннюю структуру хранения объекта и как интерпретатор с ним работает - доументация не описывает. Частично может помочь изучение возможности классов рефлексии. Доступ к "закрытым" свойствам и методам может потребоваться, например, при написании юнит-тестов.
Поведение пхп отличается от других языков? Отличается от личного понимания, то есть, идет несколько вразрез с ожиданиями, то есть поведение, местами непредсказуемое? Поздравляю, ты только что познал всю суть PHP.
В идеале - да. На практике такое неплохо работает при TDD, в иных случаях, увы, бывает всякое. Не говоря уже о том, что есть еще protected, который тоже нужно тестировать, ибо это тоже контракт.