Тот факт, что ваш пример незаконен, не нарушает LSP.Ваша проблема в том, что вы определяете интерфейс и ожидаете соблюдения этого контракта при его реализации.
Реализуя интерфейс a
, а затем пытаясь сделать сигнатуру метода несовместимой, пользователи класса b
могутпопытка вызова b::baz()
и сбой, поскольку подпись a::baz()
ожидает Baz
, а ваша несовместимая реализация на b::baz()
ожидает экземпляр Foo
.
Например, если то, что вы предлагаете, было законным, это может произойти:
$baz = new Baz();
$b = new b();
// since a::baz(Baz) is specified, the class user believes this
// should be possible, but your illegal implementation
// breaks that expectation
$b->baz($baz); // Not accepted!
Это вовсе не нарушает LSP.
Класс, который правильно реализует ваш интерфейс a
все еще может принимать объекты классов Foo
и Baz
, , поскольку объекты подтипа могут использоваться вместо объектов подтипа , точно так же, какЛСП говорит.
То, что вы не можете сделать, это написать метод с несовместимой подписью, и будущая поддержка ковариации и контравариантности также не позволит этого.
ОтносительноПоддержка ковариации и контравариантности в типах возвращаемых данных и типах параметров : в PHP 7.4 есть поддержка, поступающая в продажу в конце 2019 года.
Вы можете прочитать о деталях (принято) предложение здесь .
Ковариация будет поддерживаться только для возвращаемых типов (поэтому определения теперь могут указывать подклассы T
, если родительский класс или интерфейс объявилитип возвращаемого значения T
)
Контравариантность будет поддерживаться для типов параметров (так что подклассы или реализующие классы теперь могут объявлять супертипы T
в качестве типа параметра, если родитель илиинтерфейс объявил тип параметра T
)
При определении совместимости метода с его родительским движкомТеперь следует разрешить менее конкретные типы параметров и более конкретные возвращаемые типы, если новые типы по-прежнему принимают типы, указанные родителями.Другими словами: тип параметра может быть заменен одним из его супертипов, а возвращаемый тип может заменять подтип.
Это, опять же, позволит поддержку LSP и позволит пользователям классачтобы иметь возможность доверять абстракциям, против которых они программируют, вместо того, чтобы проверять специфику конкретного класса, который они используют.