[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: php не "видит" метод
Invis1ble
Собственно, такой тестовый код:
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 написал(а):
Родитель не знает о потомках, а потомки не знают о родителях (парадокс пыха), но он нужен для разграничения. Если написать так:


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 и показывает объект и имя метода.

Спустя 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()
можно немного изменить код, результат дампа будет тотже
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 методов.

Спустя 7 минут, 14 секунд (20.08.2011 - 18:51) Invis1ble написал(а):
Цитата
Метод __call() вызывает недоступный метод

он ничего не вызывает, он сам вызывется, если вызываемый метод не найден
Цитата
А method_exists() выводит true, потому-что приватный метод принадлежит классу наследнику

спасибо кэп biggrin.gif
Цитата
Но при вызове в callMethod происходит ошибка, так как он наследуется классом ChildClass

в том-то и дело, что наследуется, поэтому непонятно, почему ошибка. Вызов идет в контексте наследника.

UPDATE

Спустя 3 минуты, 9 секунд (20.08.2011 - 18:55) alex12060 написал(а):
Извини, что КЭПую, но все-же)
Просто изначально интерпретатор знает, кто откуда пришел...
Вызываемый метод (private) и вызывающий - с разных классов, и они не могут друг с другом совладать. Из-за этого все. Просто если вызывающий метод поместить в один класс в вызываемым, то они подружатся smile.gif

Спустя 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 члены видны снаружи класса, но не доступны.

Спустя 2 минуты, 6 секунд (20.08.2011 - 19:05) Invis1ble написал(а):
Было бы все так просто, я бы не спрашивал smile.gif

Спустя 2 минуты, 47 секунд (20.08.2011 - 19:08) alex12060 написал(а):
Invis1ble

Ну я же говорю, что private - класс, в котором он объявлен, может работать с ним, остальные - видят, но не любят его. Это объясняет все непонятки выше. Хоть и класс наследует функционал, все равно, тот функционал - отдельная галактика, её планеты не могут трогать нашу Замлю, хоть и знают о ней. ph34r.gif

Спустя 6 минут, 32 секунды (20.08.2011 - 19:15) Invis1ble написал(а):
Проблема в том, что пых почему-то считает, что вызов идет в контексте класса-родителя, хотя на самом деле вызывается callMethod из контекста наследника.
Вобщем, я все-таки склонен думать, что это баг.



Спустя 1 минута, 17 секунд Invis1ble написал(а):
Вот, надеюсь Олег сейчас растолкует smile.gif

Спустя 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

Теперь объясни мне smile.gif

Спустя 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)
С теоретической: не надо в реализации класса вызывать методы не определённые в нём (которые будут определены в его потомках).

Более того, в компилируемых языках вы бы даже не скомпилировали программу, в ПХПыхе рассматривается как фича(читай баг laugh.gif )

Спустя 2 часа, 48 минут, 46 секунд (20.08.2011 - 22:52) Invis1ble написал(а):
К сожалению, на хосте стоит 5.2, поэтому позднее связывание реализовать не получится... ((
Но мысль я понял, спасибо.

Спустя 1 день, 10 часов, 17 минут, 13 секунд (22.08.2011 - 09:10) linker написал(а):
Все эти поздние связывания служат более для статики. В нашем случае присутствуют объекты с методами унаследованными от родителей. Вызов приватного метода через контекст $this явно говорит о том, какого класса является объект - дочерний, однако PHP почему-то так не считает и в наследуемом методе используется контекст родительского класса.

Обычные методы (не статические) принадлежат объектам, а не классам, посему подобное поведение PHP удивляет и я склонен это относить к баге.

Спустя 2 дня, 11 часов, 27 минут, 28 секунд (24.08.2011 - 20:37) Guest написал(а):
linker, конкретные реализации методов относятся к конкретным классам и описывают их семантику.
Реализация метода в классе A должна оперировать только тем, что есть в классе A.

Спустя 33 секунды (24.08.2011 - 20:38) vasa_c написал(а):
ну это я, типа

Спустя 11 часов, 27 минут, 33 секунды (25.08.2011 - 08:05) linker написал(а):
vasa_c
Таким образом мы напрочь перечёркиваем понятие - наследование. Если дочерний класс получает все поля и методы своего родителя, то семантика родителя описывает и семантику его потомков. Суть в принадлежности методов, статика принадлежит классу, обычные - объектам, не зависимо от того, какого они класса. А вся соль в том, что protected методы потомков вызываются замечательно, не смотря на то, что контекст родителя.


_____________

Профессиональная разработка на заказ

Я на GitHub | второй профиль

Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.