【发布时间】:2018-09-26 08:17:32
【问题描述】:
我猜想“...必须与...兼容”是为了执行 Liskov 替换原则。但我不确定这是 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 致命错误:Declaration of Specific::create(): Specific must be compatible with General::create(): General in ...
LSP 经常被引用为:
使用基类指针或引用的函数必须能够 在不知情的情况下使用派生类的对象。
据我所知,这里没有违反这一点。那么这里有什么问题呢?是不是一些与 LSP 无关的特殊限制?它是PHP中的错误吗?我是不是在不知不觉中做错了什么?
更新:我找到了这个帖子 (Parameter type covariance in specializations)。我理解并完全同意该示例违反了 LSP。但我的情况不一样(其实相反)。
【问题讨论】:
-
我相信这是您的返回类型声明。依赖于
Specific::create返回Specific的代码如果在调用General::create时得到General类,则会中断。 -
好的,但是为特定类编写的代码无法获取通用类,因为 typehint 会阻止它通过。具体扩展一般,而不是相反。例如。
doSomethingDifferent(Specific $object)永远无法将 General 类作为 $object。 -
我认为您在使用接口时遇到了同样的问题。您期待协变行为,但 PHP 仅支持不变行为。
标签: php liskov-substitution-principle