Задачка с собеседования


В каждом языке есть свои примечательные особенности. Некоторые из них могут подпортить жизнь при отладке, другие могут позволить делать невозможное возможным. В PHP есть так же свои особенности и часто про эти особенности любят спрашивать на собеседованиях. Одна из таких задачек:

<?php
class Foo
{
private $prop = 'Hello!';

public function show($obj)
{
echo $obj->prop;
}
}
$obj = new Foo();
$obj->show( new Foo() );

Как выполнится этот код?

Размышляем… Мы пытаемся вызвать приватное свойство у объекта. По логике должна быть ошибка. Чтобы это было проще для понимания, сделаем такой код и выполним:

class Bar extends Foo
{
function __construct()
{
var_dump( $this->prop );
}
}
$obj = new Bar;

Вывод:

Notice: Undefined property: Bar::$prop in /in/t8CFo on line 23 NULL

Согласно принципам инкапсуляции наше приватное свойство скрыто даже от наследника. Выходит, что по логике, если выполнить код:

$obj2 = new Bar;
$obj1 = new Foo;
var_dump( $obj2->prop );
// Notice: Undefined property: Bar::$prop in /in/nPWa6 on line 31 NULL
var_dump( $obj1->prop );
// Fatal error: Uncaught Error: Cannot access private property Foo::$prop in /in/nPWa6:32 Stack trace:

Все работает корректно.

Но если мы напишем такой код:

( new Foo )->show( new class extends Foo { } );

Вдруг выясняется что мы получаем ответ:

string(6) "Hello!"

И вот это и есть особенность PHP. Если вы вызываете приватное свойство объекта от класса внутри методов этого класса, то приватное свойство будет доступно. И если мы возьмем пример, который был задан на собеседовании в самом начале:

( new Foo )->show( new Foo );

То так же выведется значение приватного свойства.

Итого

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

Все примеры можно проверить на всех версиях интерпретаторов прямо онлайн https://3v4l.org/PE1EV