这是几个片段:
-
压倒一切构造函数方法有一个额外的参数。
class Cat {
function __construct() {}
}
class Lion extends Cat {
function __construct($param) {}
}
-
重写(常规)方法有一个额外的参数。
class Cat {
function doSomething() {}
}
class Lion extends Cat {
function doSomething($param) {}
}
第一个会起作用,而第二个会抛出Declaration of Lion::doSomething() should be compatible with that of Cat::doSomething()
.
为什么对构造方法有特殊的态度?
要了解为什么他们受到不同对待,您必须了解里氏替换原理 https://stackoverflow.com/questions/56860/what-is-the-liskov-substitution-principle, which states http://c2.com/cgi/wiki?LiskovSubstitutionPrinciple
如果对于 S 类型的每个对象 o1 都有一个 T 类型的对象 o2,这样对于用 T 定义的所有程序 P,当 o1 替换 o2 时 P 的行为保持不变,那么 S 是 T 的子类型。” -BarbaraLiskov,数据抽象和层次结构,SIGPLAN 公告,23,5(1988 年 5 月)。
简而言之,这意味着任何使用您的课程Lion
or Cat
应该能够可靠地调用doSomething
其上,无论班级是其中之一。如果您更改方法签名,则不再保证这一点(您可以扩大它,但不能缩小它)。
非常简单的例子
public function doSomethingWithFeline(Cat $feline)
{
$feline->doSomething(42);
}
Since Lion extends Cat
,你建立了一个 is-a 关系,意思是doSomethingWithFeline
将接受一个Lion
for a Cat
。现在假设您添加一个必需的参数doSomething
in Lion
。上面的代码会中断,因为它没有传递新参数。因此,需要兼容的签名。
LSP 不适用于构造函数 https://stackoverflow.com/questions/5490824/should-constructors-comply-with-the-liskov-substitution-principle尽管,因为子类型可能有不同的依赖关系 https://softwareengineering.stackexchange.com/questions/178886/liskov-substitution-and-abstract-classes-strategy-pattern。例如,如果您有一个 FileLogger 和一个 DBLogger,则第一个的构造函数将需要文件名,而后者将需要数据库适配器。因此,ctor 是关于具体实现的,而不是类之间契约的一部分。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)