class ParentClass {
public function __call($methodName, $args) {
var_dump($this, $methodName, method_exists($this, $methodName));
echo '<br />o_O WTF?! Called unknown method ' . $methodName . ' of object ' . get_class($this);
}
protected function callMethod($methodName) {
return $this->$methodName();
}
}
class ChildClass extends ParentClass {
public function __construct() {
$this->callMethod('privateMethod');
}
private function privateMethod() {
echo 'OK';
}
}
$object = new ChildClass;
Кто что может сказать по этому поводу?
Спустя 11 минут, 23 секунды (20.08.2011 - 18:19) alex12060 написал(а):
Ну если ты пытаешься вызвать private метод, то все так, все и должно быть.
Спустя 1 минута, 40 секунд alex12060 написал(а):
Родитель не знает о потомках, а потомки не знают о родителях (парадокс пыха), но он нужен для разграничения. Если написать так:
То результат будет - ОК
Спустя 1 минута, 40 секунд alex12060 написал(а):
Родитель не знает о потомках, а потомки не знают о родителях (парадокс пыха), но он нужен для разграничения. Если написать так:
class ParentClass {
public function __call($methodName, $args) {
var_dump($this, $methodName, method_exists($this, $methodName));
echo '<br />o_O WTF?! Called unknown method ' . $methodName . ' of object ' . get_class($this);
}
}
class ChildClass extends ParentClass {
public function __construct() {
$this->callMethod('privateMethod');
}
protected function callMethod($methodName) {
return $this->$methodName();
}
private function privateMethod() {
echo 'OK';
}
}
$object = new ChildClass;
То результат будет - ОК
Спустя 2 минуты, 1 секунда (20.08.2011 - 18:21) Invis1ble написал(а):
alex12060
я ведь вызываю его от имени дочернего объекта, обрати внимание на дамп, который выдает true и показывает объект и имя метода.
я ведь вызываю его от имени дочернего объекта, обрати внимание на дамп, который выдает true и показывает объект и имя метода.
Спустя 4 минуты, 37 секунд (20.08.2011 - 18:25) alex12060 написал(а):
Метод method_exists() ищет по всем методам, не зависимо от их области видимости. Если я не ошибаюсь, то после наследования, результирующий класс получится таким:
Щас проверим.
Хотя я уже ушел от вопроса, щас разберемся :)
class ChildClass {
public function __call($methodName, $args) {
var_dump($this, $methodName, method_exists($this, $methodName));
echo '<br />o_O WTF?! Called unknown method ' . $methodName . ' of object ' . get_class($this);
}
protected function callMethod($methodName) {
return $this->$methodName();
}
public function __construct() {
$this->callMethod('privateMethod');
}
protected function callMethod($methodName) {
return $this->$methodName();
}
private function privateMethod() {
echo 'OK';
}
}
Щас проверим.
Хотя я уже ушел от вопроса, щас разберемся :)
Спустя 3 минуты, 24 секунды (20.08.2011 - 18:29) Invis1ble написал(а):
что ты этим хочешь сказать? я говорю о том, что дамп ясно показывает, что метод существует, но в то же время срабатывает __call()
можно немного изменить код, результат дампа будет тотже
Спустя 2 минуты, 15 секунд Invis1ble написал(а):
Т.е. метод существует, но почему-то вызывается __call()
можно немного изменить код, результат дампа будет тотже
class ParentClass {
public function __call($methodName, $args) {
echo '<br />o_O WTF?! Called unknown method ' . $methodName . ' of object ' . get_class($this);
}
protected function callMethod($methodName) {
var_dump($this, $methodName, method_exists($this, $methodName));
return $this->$methodName();
}
}
class ChildClass extends ParentClass {
public function __construct() {
$this->callMethod('privateMethod');
}
private function privateMethod() {
echo 'OK';
}
}
$object = new ChildClass;
Спустя 2 минуты, 15 секунд Invis1ble написал(а):
Т.е. метод существует, но почему-то вызывается __call()
Спустя 15 минут, 30 секунд (20.08.2011 - 18:44) alex12060 написал(а):
Метод __call() вызывает недоступный метод, просто он поставлен в родительском классе, а не в дочернем. Ведь в мануале написано, что доступ к private методам имеет только класс, в котором он объявлен, вывод, он наследуется. А method_exists() выводит true, потому-что приватный метод принадлежит классу наследнику. Но при вызове в callMethod происходит ошибка, так как он наследуется классом ChildClass.
Тут в общем всю песню играет область видимости private методов.
Тут в общем всю песню играет область видимости private методов.
Спустя 7 минут, 14 секунд (20.08.2011 - 18:51) Invis1ble написал(а):
Цитата |
Метод __call() вызывает недоступный метод |
он ничего не вызывает, он сам вызывется, если вызываемый метод не найден
Цитата |
А method_exists() выводит true, потому-что приватный метод принадлежит классу наследнику |
спасибо кэп
Цитата |
Но при вызове в callMethod происходит ошибка, так как он наследуется классом ChildClass |
в том-то и дело, что наследуется, поэтому непонятно, почему ошибка. Вызов идет в контексте наследника.
UPDATE
Спустя 3 минуты, 9 секунд (20.08.2011 - 18:55) alex12060 написал(а):
Извини, что КЭПую, но все-же)
Просто изначально интерпретатор знает, кто откуда пришел...
Вызываемый метод (private) и вызывающий - с разных классов, и они не могут друг с другом совладать. Из-за этого все. Просто если вызывающий метод поместить в один класс в вызываемым, то они подружатся
Просто изначально интерпретатор знает, кто откуда пришел...
Вызываемый метод (private) и вызывающий - с разных классов, и они не могут друг с другом совладать. Из-за этого все. Просто если вызывающий метод поместить в один класс в вызываемым, то они подружатся
Спустя 2 минуты, 48 секунд (20.08.2011 - 18:57) Invis1ble написал(а):
alex12060
Цитата |
Вызываемый метод (private) и вызывающий - с разных классов, и они не могут друг с другом совладать. Из-за этого все |
с каких разных, если метод callMethod() унаследован наследником (я ведь создаю объект ChildClass), следовательно вызов в его контексте. Что подтверждается var_dump()
Спустя 4 минуты, 25 секунд Invis1ble написал(а):
Цитата |
Просто если вызывающий метод поместить в один класс в вызываемым, то они подружатся |
это да, также проблема решается повышением уровня доступа до protected. Меня интересует в данном случае причина, а не как решить проблему.
Спустя 5 минут, 52 секунды (20.08.2011 - 19:03) alex12060 написал(а):
Было бы все так просто, нужды в private не было.
Лаконично, определение модификатора private звучит так: Private члены видны снаружи класса, но не доступны.
Лаконично, определение модификатора private звучит так: Private члены видны снаружи класса, но не доступны.
Спустя 2 минуты, 6 секунд (20.08.2011 - 19:05) Invis1ble написал(а):
Было бы все так просто, я бы не спрашивал
Спустя 2 минуты, 47 секунд (20.08.2011 - 19:08) alex12060 написал(а):
Invis1ble
Ну я же говорю, что private - класс, в котором он объявлен, может работать с ним, остальные - видят, но не любят его. Это объясняет все непонятки выше. Хоть и класс наследует функционал, все равно, тот функционал - отдельная галактика, её планеты не могут трогать нашу Замлю, хоть и знают о ней.
Ну я же говорю, что private - класс, в котором он объявлен, может работать с ним, остальные - видят, но не любят его. Это объясняет все непонятки выше. Хоть и класс наследует функционал, все равно, тот функционал - отдельная галактика, её планеты не могут трогать нашу Замлю, хоть и знают о ней.
Спустя 6 минут, 32 секунды (20.08.2011 - 19:15) Invis1ble написал(а):
Проблема в том, что пых почему-то считает, что вызов идет в контексте класса-родителя, хотя на самом деле вызывается callMethod из контекста наследника.
Вобщем, я все-таки склонен думать, что это баг.
Спустя 1 минута, 17 секунд Invis1ble написал(а):
Вот, надеюсь Олег сейчас растолкует
Вобщем, я все-таки склонен думать, что это баг.
Спустя 1 минута, 17 секунд Invis1ble написал(а):
Вот, надеюсь Олег сейчас растолкует
Спустя 4 минуты, 10 секунд (20.08.2011 - 19:19) vasa_c написал(а):
Нагородили каких-то КалМетодов. Пример гораздо проще:
И ответ гораздо чОтче:
class A {
public function x() {
$this->y();
}
}
class B extends A {
private function y() {
}
}
$obj = new B();
$obj->x();
И ответ гораздо чОтче:
Цитата |
Fatal error: Call to private method B::y() from context 'A' |
Спустя 1 минута, 41 секунда vasa_c написал(а):
"Контекст" (набор методов) привязан к классу, а не к объекту.
Спустя 2 минуты, 50 секунд (20.08.2011 - 19:22) Invis1ble написал(а):
vasa_c
Цитата |
from context 'A' |
почему from context A ? это нормально? мы ж создаем объект B...
Спустя 33 секунды Invis1ble написал(а):
Цитата |
"Контекст" (набор методов) привязан к классу, а не к объекту. |
Все ясно, спасибо за ответ )
Спустя 1 минута, 17 секунд (20.08.2011 - 19:23) alex12060 написал(а):
Invis1ble
Теперь объясни мне
Теперь объясни мне
Спустя 1 минута, 55 секунд (20.08.2011 - 19:25) Invis1ble написал(а):
alex12060
ну как я написал до этого, пых считает, что метод вызывается от имени другого класса
ну как я написал до этого, пых считает, что метод вызывается от имени другого класса
Спустя 9 минут, 51 секунда (20.08.2011 - 19:35) vasa_c написал(а):
С технической точки зрения: методы привязаны к классам в которых определены.
Из-за этого недавно ввели позднее связывание
С теоретической: не надо в реализации класса вызывать методы не определённые в нём (которые будут определены в его потомках).
class A {
public function x() {
var_dump(__CLASS__);
var_dump(get_class(new self));
}
}
class B extends A {
}
$obj = new B;
$obj->x(); // A A
Из-за этого недавно ввели позднее связывание
С теоретической: не надо в реализации класса вызывать методы не определённые в нём (которые будут определены в его потомках).
Спустя 28 минут, 52 секунды (20.08.2011 - 20:04) AlexWindHope написал(а):
Цитата (vasa_c @ 20.08.2011 - 16:35) |
С теоретической: не надо в реализации класса вызывать методы не определённые в нём (которые будут определены в его потомках). |
Более того, в компилируемых языках вы бы даже не скомпилировали программу, в ПХПыхе рассматривается как фича(читай баг )
Спустя 2 часа, 48 минут, 46 секунд (20.08.2011 - 22:52) Invis1ble написал(а):
К сожалению, на хосте стоит 5.2, поэтому позднее связывание реализовать не получится... ((
Но мысль я понял, спасибо.
Но мысль я понял, спасибо.
Спустя 1 день, 10 часов, 17 минут, 13 секунд (22.08.2011 - 09:10) linker написал(а):
Все эти поздние связывания служат более для статики. В нашем случае присутствуют объекты с методами унаследованными от родителей. Вызов приватного метода через контекст $this явно говорит о том, какого класса является объект - дочерний, однако PHP почему-то так не считает и в наследуемом методе используется контекст родительского класса.
Обычные методы (не статические) принадлежат объектам, а не классам, посему подобное поведение PHP удивляет и я склонен это относить к баге.
Обычные методы (не статические) принадлежат объектам, а не классам, посему подобное поведение PHP удивляет и я склонен это относить к баге.
Спустя 2 дня, 11 часов, 27 минут, 28 секунд (24.08.2011 - 20:37) Guest написал(а):
linker, конкретные реализации методов относятся к конкретным классам и описывают их семантику.
Реализация метода в классе A должна оперировать только тем, что есть в классе A.
Реализация метода в классе A должна оперировать только тем, что есть в классе A.
Спустя 33 секунды (24.08.2011 - 20:38) vasa_c написал(а):
ну это я, типа
Спустя 11 часов, 27 минут, 33 секунды (25.08.2011 - 08:05) linker написал(а):
vasa_c
Таким образом мы напрочь перечёркиваем понятие - наследование. Если дочерний класс получает все поля и методы своего родителя, то семантика родителя описывает и семантику его потомков. Суть в принадлежности методов, статика принадлежит классу, обычные - объектам, не зависимо от того, какого они класса. А вся соль в том, что protected методы потомков вызываются замечательно, не смотря на то, что контекст родителя.
Таким образом мы напрочь перечёркиваем понятие - наследование. Если дочерний класс получает все поля и методы своего родителя, то семантика родителя описывает и семантику его потомков. Суть в принадлежности методов, статика принадлежит классу, обычные - объектам, не зависимо от того, какого они класса. А вся соль в том, что protected методы потомков вызываются замечательно, не смотря на то, что контекст родителя.
_____________
Профессиональная разработка на заказ
Я на GitHub | второй профиль