Я полагаю, что «… должно быть совместимо с …» для обеспечения соблюдения принципа замены Лискова. Но я не уверен, что это то, что говорит LSP?
У меня есть такой код:
class General
{
public static function create(): General
{
return new static;
}
public function doSomething()
{
echo get_class($this) . ' speaking!' . PHP_EOL;
}
}
class Specific extends General
{
public static function create(): Specific
{
return parent::create();
}
}
function doSomething(General $object)
{
$object->doSomething();
}
doSomething(General::create());
doSomething(Specific::create());
Который производит:
Фатальная ошибка PHP: Объявление Specific :: create (): Specific должно быть совместимо с General :: create (): General в …
LSP часто упоминается как:
Функции, которые используют указатели или ссылки на базовые классы, должны быть в состоянии
использовать объекты производных классов, не зная этого.
И это не нарушено здесь, насколько я понимаю. Так что здесь не так? Это какое-то особое ограничение, которое не имеет ничего общего с LSP? Это ошибка в PHP? Я делаю что-то не так, не зная?
ОБНОВЛЕНИЕ: я нашел эту тему (Тип параметра ковариация в специализациях). Я понимаю и полностью согласен, что пример там нарушает LSP. Но у меня ситуация другая (на самом деле наоборот).
http://php.net/manual/en/functions.returning-values.php
При переопределении родительского метода дочерний метод должен соответствовать любому объявлению возвращаемого типа в родительском методе. Если родитель не определяет тип возвращаемого значения, тогда дочерний метод может сделать это.
Ваш Specific::create
функция должна указывать General
тип возврата.
В противном случае код написан для Specific::create
потенциально может сломаться при запуске General::create
как бы получил другой класс.
Других решений пока нет …