Я смутил из примера в php manual. Речь идет о видимости. Вот пример.
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(); ?>
http://www.php.net/manual/en/language.oop5.visibility.php
Этот пример выводит
Bar::testPrivate Foo::testPublic
Пожалуйста, объясните, как это происходит?
почему оба testPublic()
не называются?
Я поместил var_dump($this)
в конструкцию класса Bar. Он печатает object(Foo)[1]
. То, что я знаю, это частные свойства, которые можно вызвать с тем же классом.
Тогда как Bar::testPrivate
« Bar::testPrivate
»?
Тогда как вызывается «Bar :: testPrivate»?
Когда вы вызываете $myFoo->test()
, он запускает код в контексте Bar
потому что класс Foo
не переопределяет его.
Inside Bar::test()
, когда $this->testPrivate()
, интерпретатор сначала будет искать Foo
но этот метод является закрытым (и частные методы из классов потомков нельзя вызывать из Bar
), поэтому он на один уровень до тех пор, пока не найдет подходящий метод; в этом случае это будет Bar::testPrivate()
.
Напротив, когда $this->testPublic()
, интерпретатор немедленно находит подходящий метод в Foo
и запускает его.
редактировать
почему оба testPublic () не называются?
$this->testPublic()
только один метод, когда вы запускаете $this->testPublic()
, самый дальний (с точки зрения расстояния до базового класса).
Если Foo::testPublic()
также должен выполнить реализацию родителя, вы должны написать parent::testPublic()
внутри этого метода.
Ваша функция лежит в классе Bar
и вы используете волшебный $this
указатель для вызова функций-членов.
Попробуйте переместить функцию test()
в класс Foo
и посмотреть, что произойдет. Выход должен быть:
Foo::testPrivate Foo::testPublic
В вашем примере была вызвана частная функция Bar, поскольку она применима только к этому классу. Класс Foo не имеет в нем test
функции, и, следовательно, тестовая функция класса Bar
не имеет доступа к вызову.
Тогда публичная функция класса Foo
была вызвана вместо Bar
из-за перегрузки функции.
Оба класса имеют функцию этого имени, поэтому функция дочернего класса имеет значение.
Ты звонишь
$myFoo->test();
См. Функциональный test
:
public function test() { $this->testPrivate(); $this->testPublic(); }
Когда это вызывается в экземпляре класса Bar
(включая унаследованные классы), он вызывает testPrivate
и testPublic
.
Эти методы переопределяются в классе Foo
, это означает, что используются методы Foo
. Вы всегда можете вызывать метод базового класса:
// in Foo public function testPublic() { parent::testPublic(); echo "Foo::testPublic\n"; }
Bar::testPrivate
вызывается потому, что он является private
и не переопределяется Foo::testPrivate
.
См. Больше здесь или здесь .
Private
не означает, что вы не можете это назвать. Это означает, что вы можете вызывать его только из текущего класса . Public
означает, что вы можете назвать это из любого класса .
Чтобы вызвать Bar::testPrivate
, попробуйте следующее:
$Bar->testPublic();
или
parent::testPublic();
НО, вы не можете вызвать $Bar->testPrivate()
потому что метод является private
.
Я предполагаю, что комментарий пользователя «omega at 2093 dot es» ( http://www.php.net/manual/en/language.oop5.visibility.php#109324 ) описывает одно и то же. Там сказано: «Методы, определенные в родительском классе, не могут получить доступ к приватным методам, определенным в классе, который наследует их. Однако они могут получить доступ к защищенным».
В вашем случае $this
объект в методе Bar::test()
имеет тип Foo
(ваш var_dump доказывает это). Поскольку метод Foo::testPrivate()
является закрытым, доступ к нему из класса родительского класса невозможен, и единственный доступный доступ к нему остается Bar::testPrivate()
(попробуйте комментировать определение, и вы получите фатальную ошибку) , Поэтому первый вывод – Bar::testPrivate
.
Строка $this->testPublic();
вызывает метод Foo::testPublic()
, поскольку $this
имеет тип Foo
и метод, определяется как public.
Короче говоря, частные методы доступны только из класса, где они определены. К ним нельзя обращаться ни от ребенка, ни от родительских классов.
Чтобы доступ к этому методу из дочерних или родительских классов, он защищен. Например, если вы сделаете testPrivate()
защищенным в обоих классах, он напечатает Foo::testPrivate Foo::testPublic
.
Класс Foo расширяет класс Bar. Тогда функция test называется wich определена в Bar. В этой функции есть два вызова. Один для публики и один для частной функции в классе Bar.