我想知道我应该如何组织我的两个课程。
Knife
:只是一个简单,坚实,基本的,就像一把菜刀。PocketKnife
,其状态为已打开或已关闭。class Knife{
public function cut() {/* do the cutting */}
}
class PocketKnife extends Knife{
private $opened = 0; // 0/1
// ...
public function cut() {
if ($this->opened) {
parent::cut();
}
}
}
我的代码中的所有类都不是抽象的。
这个例子是否违反了LSP?
在我看来确实如此,因为cut()
操作的后置条件应为:
但是当已关闭状态的PocketKnife
时,我们不会有这些后置条件。或者我错了吗?
答案 0 :(得分:1)
是否违反LSP,取决于" cut"的定义。是(不应该)。如果操作的后置条件是以下必须为真:
然后,当关闭"关闭时,PocketKnife不符合这些条件。因此,PocketKnife无法在任何地方替换Knife并且LSP被破坏。
如何解决?
嗯,这取决于上下文,需要更多信息。但是,一个例子可能是这样的:
class Knife{
public function cut() {/* do the cutting */}
}
class PocketKnife extends Knife{
private $opened = 0; // 0/1
// ...
public function cut() {
if (!$this->opened) {
// state is changed for cut to be performed.
$this->opened = 1;
parent::cut();
// may need to close again, after operation.
}
}
}
这样,LSP就不会被破坏。再一次,这个例子只是提出了解决这类问题的方法。
答案 1 :(得分:0)
Liskov替换原则(最简单的OOP设计指南之一)简单地指出任何子类型必须可以替代其父类而不破坏程序。
如果你有像someFunc(Knife k)这样调用k.cut()的方法,你可以将Knife或Pocketknife或WhateverKnife传递给someFunc方法并使程序正常工作,那么你就不会违反LSP。