Ответ 1
Наследование/переопределение частных методов
В PHP методы (включая частные) в подклассах:
- скопирован; объем исходной функции поддерживается.
- Заменено ( "переопределено", если вы хотите).
Вы можете увидеть это с помощью этого кода:
<?php
class A {
//calling B::h, because static:: resolves to B::
function callH() { static::h(); }
private function h() { echo "in A::h"; }
}
class B extends A {
//not necessary; just to make explicit what happening
function callH() { parent::callH(); }
}
$b = new B;
$b->callH();
Теперь, если вы переопределите частный метод, его новая область не будет A, это будет B, и вызов завершится неудачно, потому что A::callH()
работает в области A
:
<?php
class A {
//calling B::h, because static:: resolves to B::
function callH() { static::h(); }
private function h() { echo "in A::h"; }
}
class B extends A {
private function h() { echo "in B::h"; }
}
$b = new B;
$b->callH(); //fatal error; call to private method B::h() from context 'A'
Методы вызова
Здесь следующие правила:
- Посмотрите в таблицу методов фактического класса объекта (в вашем случае
bar
).- Если это дает закрытый метод:
- Если область, в которой был определен метод, совпадает с областью действия вызывающей функции и совпадает с классом объекта, используйте его.
- В противном случае просмотрите родительские классы для частного метода с той же областью действия, что и вызывающая функция и с тем же именем.
- Если метод не найден, который удовлетворяет одному из вышеперечисленных требований, выполните сбой.
- Если это дает общедоступный/защищенный метод:
- Если область действия метода отмечена как измененная, мы можем переопределить частный метод с помощью общедоступного/защищенного метода. Таким образом, в этом случае, и, кроме того, там используется метод с тем же именем, который является private, как определено для области вызывающей функции.
- В противном случае используйте найденный метод.
- Если это дает закрытый метод:
Заключение
- (оба частные) Для
bar->call()
областьcall
равнаfoo
. Вызов$this->m()
вызывает поиск в таблице методовbar
дляm
, что дает частныйbar::m()
. Однако областьbar::m()
отличается от области вызова, котораяfoo
. Методfoo:m()
найден при прохождении иерархии и используется вместо этого. - (Закрыто в
foo
, public вbar
) Объемcall
по-прежнемуfoo
. Результатом поиска является публикацияbar::m()
. Однако его область помечена как измененная, поэтому поиск выполняется в таблице функций области вызоваfoo
для методаm()
. Это дает частный методfoo:m()
с той же областью действия, что и область вызова, поэтому используется вместо этого. - Здесь ничего не видно, потому что видимость снижена.
- (Оба общедоступных) Объем
call
по-прежнемуfoo
. Результатом поиска является публикацияbar::m()
. Его область не помечена как измененная (они оба являются общедоступными), поэтому используетсяbar::m()
.