И все-таки, завися от реального класса(тем более финального), между этими двумя классами теперь большая связь. Вижу в этом нарушение Open Closed принципа.
Во-первых, OCP — это про изменение на регулярной основе. Класс должен
стремиться к точке «равновесия»: когда изменения вносить не придётся, но по пути к этой точке он может и должен меняться. Если понадобится там интерфейс вместо final class — поменяешь. Из утверждения, что зависимость от final class — нарушение OCP, следует, что эта зависимость именно от интерфейса обязательно понадобится. Это заведомо ошибочная предпосылка, я уже приводил примеры, когда интерфейс будет вреден и вводить его никто не будет.
Во-вторых, напомню про coupling vs cohesion. Ты под «зависимостью», судя по всему, обязательно понимаешь coupling. В то время как два класса могут быть специально жестко взаимосвязаны для повышения так называемой связности. Это как в том давнем примере с расчётом расстояния, где был захардкожен радиус Земли прямо в сущности. Помнится, ты возмущался, что это жёсткая зависимость. Да, это жёсткая зависимость, потому что мы делали модель расчёта конкретно для земных условий, а не абстрактную модель в вакууме для любой планеты. Там было что-то связано с путешествиями. Вот будут у компании Acme туры по Марсу, можно будет подумать об изменении модели. Хотя даже в таком случае, вероятно, проще сделать две отдельные модели, потому что они могут сильно отличаться.
В-третьих, возвращаюсь снова и снова к одной и той же мысли: как раз если у тебя нет никаких маркеров:
PHP:
public function __construct(UserRepository $userRepository)
, то ты
не знаешь final class перед тобой или нет. В этом и смысл: ты можешь заменить реализацию контракта и consumer про это даже не узнает. А если ты вводишь маркер, то ты сам вводишь дополнительную зависимость: ты говоришь, что вот это интерфейс/класс и прозрачно поменять это уже не получится.