TGViewer
Пых Пых @phpyh · 7.85K subscribers
Post #806 7.04K
Проблемы родственных классов

Небольшой детектив вам на ночь в субботу.

Вы наверняка знаете, что наследники одного и того же базового класса могут читать друг у друга защищённые свойства, объявленные в этом базовом классе:


abstract class Father
{
protected string $data = 'x';
}

final class Son extends Father {}

final class Daughter extends Father
{
public function iCanSeeBrothersProtected(Son $brother): void
{
echo $brother->data;
}
}

// выведет x
new Daughter()->iCanSeeBrothersProtected(new Son());


Я, кстати, не могу согласиться с Сашей Макаровым, что это прям в чистом виде механизм дружественных классов в PHP. Всё-таки в других языках "дружба" декларируется специальным ключевым словом friend между классами из несвязанных иерархий. В нашем случае это, скорее, "родственники". Но сейчас речь не об этом.

На днях в internals Jonathan Vollebregt обратил внимание на интересное поведение защищённого свойства при его переопределении:


final class Son extends Father
{
// просто переопределяем свойство, ничего не меняя
protected string $data = 'x';
}

// и теперь выбрасывает Cannot access protected property Son::$data
new Daughter()->iCanSeeBrothersProtected(new Son());


Вопрос: это баг или нет?

Для начала надо понять, является ли вообще доступ к общим защищённым свойствам из родственных классов официальной фичёй PHP? В документации по видимости из фразы "members declared protected can be accessed only within the class itself and by inheriting and parent classes" такое поведение однозначным образом не следует. В других C-подобных языках такого тоже нет: C#, Kotlin.

Однако, пробежавшись по всем ссылкам статьи PHP friendly классы Саши Макарова, я нашёл тикет #37632 от мая 2006 года, который просит исправить отсутствие такой фичи как баг, и его исправляют в PHP 5.2! Далее в 2020 Никита Попов отвечает Саше в Твиттере, что такое поведение "looks fine" и не поменяется в будущем.

В таком случае кажется более логичным добавить в доку всю эту информацию, а также исправить текущее поведение при переопределении, чтобы всё было консистентно... Что вы думаете по этому поводу?

В любом случае я бы не рекомендовал таким пользоваться. Все эти игры с наследованием и видимостью оправданы разве что в недрах какого-нибудь фреймворка в классах с пометкой @internal. В бизнесовом же проекте чем понятнее код, тем ниже вероятность, что его перепишут на Go. 😅
  • 🔥 58
  • 👍 30
  • ❤ 11
  • 😁 9
  • 💯 2
More from @phpyh
  1. Sep 15, 2026Сейчас один человек с AI может выполнять работу целого IT-отдела. Только хуёво
  2. Sep 12, 2026Спасибо за заявки! Всем напишу в понедельник. Осталось 1 место.
  3. Sep 11, 2026Хардкорный курс асинхронного PHP https://hardcourse.ru/php/async
  4. Sep 11, 2026Ещё полчасика надо — сайт готов, расписываю программу! 🙏
  5. Sep 10, 2026Краткое содержание: завтра в 12:00 открываю набор на Хардкорный курс асинхронного PHP с уч…
  6. Sep 10, 2026Post #1011
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →