Наследование и видимость - PHP
Мне трудно понять, почему мы получаем вывод этого кода:
<?php
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "Bar::testPublic\n";
}
private function testPrivate() {
echo "Bar::testPrivate\n";
}
}
class Foo extends Bar
{
public function testPublic() {
echo "Foo::testPublic\n";
}
private function testPrivate() {
echo "Foo::testPrivate\n";
}
}
$myFoo = new foo();
$myFoo->test();
?>
Итак, Foo расширяет Bar. $myfoo является предметом класса Foo. Foo не имеет метода, называемого test(), поэтому он расширяет его из своей родительской панели. Но почему результат test() -
Bar::testPrivate
Foo::testPublic
Не могли бы вы объяснить мне, почему первый не Foo:: testPrivate, когда этот родительский метод переопределен в дочернем?
Спасибо вам заблаговременно!
Ответы
Ответ 1
Вероятно, потому что testPrivate
, как уже упоминалось ранее, является частным методом и не будет наследоваться/перезаписываться наследованием класса.
На странице руководства php.net вы, вероятно, получили тот код, из которого явно указано, что We can redeclare the public and protected method, but not private
Итак, что именно происходит, следующее: дочерний класс не будет обновлять метод testPrivate
, но вместо этого создает свою собственную версию в "области", если только дочерний объект. Поскольку test()
определяется в родительском классе, он будет обращаться к родителям testPrivate
.
Если вы переопределили функцию test
в дочернем классе, она должна получить доступ к методу childs ? testPrivate()
.
Ответ 2
Члены private
не могут быть переопределены, только общественные и защищенные. Это означает, что на самом деле testPrivate
отключен не, поэтому Bar
не может его видеть и по-прежнему вызывает свой собственный testPrivate
.
Ответ 3
Частные методы не видны никому, кроме класса объявления. Поскольку вы вызываете testPrivate
из родительского класса, единственным способом, к которому он имеет доступ, является его собственное объявление метода. Таким образом, вы получаете результат, который видите. Однако если модификатор доступа был protected
, то вы получите ожидаемый результат, так как защищенные методы видны во всей цепочке наследования.
Ответ 4
Потому что private
означает private
. Никакой другой класс, даже класс детей не знает о Bar::testPrivate()
и поэтому не может переопределить то, о чем они даже не знают.
Вы можете использовать Foo::testPrivate()
только внутри Foo
. Потому что это то, о чем private
.
Дополнительная информация: Странное поведение при переопределении частных методов
Ответ 5
Из manual:
Участникам, объявленным как private, может быть доступен только класс, который определяет член.
Поскольку ваша тестовая функция работает в баре базового класса, она будет обращаться к частной функции в своем классе.
Ответ 6
Это не специфично для PHP. Правила наследования требуют, чтобы защищенные и публичные функции были переопределяемыми. Частные функции имеют свой собственный масштаб и невидимы для обобщенного класса.
Ниже приведена аналогичная ситуация на Java, такой же результат:
Bar::testPrivate
Foo::testPublic
Кроме того, вы можете получить предупреждение
The method testPrivate() from the type Foo is never used locally Foo.java
так как скомпилирована Java.
public class Bar
{
public void test() {
this.testPrivate();
this.testPublic();
}
public void testPublic() {
System.out.println("Bar::testPublic\n)");
}
private void testPrivate() {
System.out.println( "Bar::testPrivate\n");
}
}
public class Foo extends Bar {
public void testPublic() {
System.out.println("Foo::testPublic\n");
}
private void testPrivate() {
System.out.println("Foo::testPrivate\n");
}
public static void main(String[] args) {
Foo myFoo = new Foo();
myFoo.test();
}
}