Как работает Наследование и область видимости в PHP?

90
02 июля 2021, 11:30
<?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(); // Bar::testPrivate 
// Foo::testPublic

Паблик он берет из дочернего класса, А приватный из своего. Что совсем не логично. Ведь он не может достать ПриватныйМетод. Ведь он не наследуется.

public function test() {
$this->testPrivate();//По сути в объекте нашего класса его нет, он же не наследуется, т.к. Приватное
$this->testPublic();
}

И это первый вопрос, каким образом это работает, что вызывается метод, который не наследуется, в других языках я вроде такого не встречал.

ВТОРОЕ.Я думал что т.к. я наследовал класс, то теперь типо test есть в моем наследованном классе, и он может работать со всеми моими методами. Но вызвать Приватный метод в дочернем классе он не может.

Answer 1

Класс Foo расширил класс Bar, унаследовал метод test() и перегрузил метод testPrivate(). Но т.к. данный метод private, он (перегруженный testPrivate()) вне области видимости класса Bar. По этой причине класс Bar вызывает тот testPrivate(), который видит - свой.

upd:

Вы не наследуете test() в абсолютном понимании этого термина. Слово extends переводится как РАСШИРЯЕТ, это оно и означает. Класс Foo расширил функционал класса Bar. $myFoo будет определятся php и как экземпляр класса Bar

$myFoo = new Foo();
echo ($myFoo instanceof Foo); //output = 1
echo ($myFoo instanceof Bar); //output = 1

upd2:

До тех пор пока эти методы не будут переопределены, они будут сохранять свою исходную функциональность. (https://www.php.net/manual/ru/language.oop5.inheritance.php)

Методы с модификатором доступа private не перегружаются (не переопределяются).

upd3:

... Я спрашиваю почему они оказывается в объекте дочернего класса, приватные методы и свойства ?

Они там не оказываются. Спросите себя, почему test() вообще был вызван? Потому, что интерпретатор сперва проверил родительский класс Bar, нашёл там tect(), далее проверил дочерний Foo, не нашёл там перегруженный tect() и начал интерпретировать test() в Bar. Далее, перейдя на $this->testPrivate(); он, по той же схеме, нашёл данный метод в Bar, не нашёл (нашёл, но модификатором ему запрещено его выполнять, ведь он в данный момент в классе Bar) private testPrivate() и выполнил найденный.

Хорошая статья вот

upd4:

Касаемо приватных свойств.

class Bar
{
    private $a = 'some';
}
class Foo extends Bar
{}
var_dump(new Foo);
// Foo Object
// (
//     [a:Bar:private] => some
// )

[a:Bar:private] => some не означает, что класс Bar содержит данное свойство. Это лишь указатель на то, что где-то в цепочке родителей класса Foo (в данном случае в Bar) есть приватное свойство. Собственно из записи дампа всё и так ясно.

[имя:a:класс:Bar:модификатор доступа:private]

В памяти компьютера под класс создаётся структура zend_class_entry, среди полей которой есть parent- указатель (ссылка) на родителей данного класса. По этой ссылке в var_dump класса Foo попадает private $a класса Bar.

Очень в общем, но суть, думаю, ясна.

Answer 2

Документация по PHP:

Например, при расширении класса дочерний класс наследует все общедоступные и защищенные методы из родительского класса. До тех пор пока эти методы не будут переопределены, они будут сохранять свою исходную функциональность.

Определите методы testPrivate() не private, а protected.

READ ALSO
Php на продакшн

Php на продакшн

Есть проект на PHP, посоветуйте способы как удобно и красиво заливать изменения на продакшнЖелательно хранить несколько последних версий...

134
Эмуляция Enum, но с доп. методами. Корректно ли?

Эмуляция Enum, но с доп. методами. Корректно ли?

В языке C# есть перечисления (enum)Удобная вещь, чтобы не заводить магические числа/строки/значения

129
Не выполняется php из консоли Ubuntu

Не выполняется php из консоли Ubuntu

Запускаю из консоли php файл на выполнение, но никакого результата нетОшибку не выдаёт никакую, но и код не выполняется

100
Вывод данных из таблицы в разные блоки div class

Вывод данных из таблицы в разные блоки div class

Нужно вывести значения из таблицы в один div блок, где две заметки (картинка, название, краткое описание и тд

121