我处于与Code Complete中提到的Steve McConnell's非常相似的情况。只有我的问题是基于车辆和三轮车碰巧在法律属于汽车类。到目前为止,汽车有四个车轮。任何方式我的域名是不必要的复杂,所以很容易坚持下面的猫的例子。如何避免违反Liskov替代原则(LSP)?
要怀疑重写常规做内 任何派生例行这通常表明在 基类设计中的错误类。例如,假设你有一个类Cat和一个例程Scratch(),并且假设你最终发现有一些 猫被声明并且不能从头开始。您可能会试图创建一个从名为ScratchlessCat的Cat派生的类 ,并覆盖Scratch() 例程以便不执行任何操作。这种方法存在几个问题:
它违反了抽象(接口契约)通过改变其接口的语义在猫 类呈现。
当您将其扩展到其他 派生类时,此方法会很快失去控制。当你发现没有尾巴的猫时会发生什么?还是一只不抓老鼠的猫?还是不喝牛奶的猫? 最终,你会最终得到派生类,如 ScratchlessTaillessMicelessMilklessCat。
随着时间的推移,这种方法会产生令人困惑的代码,因为祖先类的接口和行为对其后代的行为意义不大或根本没有意义。
解决此问题的地方不在基类中,而是在原始Cat类的 中。创建一个Claws类,并将其包含在Cat类的 中。根本问题是假设所有的猫从头开始, 所以从源头上解决这个问题,而不是仅仅在目的地包扎 。
根据他上面的伟大的书的文字。以下是坏
父类并不一定是抽象
public abstract class Cat {
public void scratch() {
System.out.println("I can scratch");
}
}
派生类
public class ScratchlessCat extends Cat {
@Override
public void scratch() {
// do nothing
}
}
现在,他建议创建另一个类Claws
,但我不明白怎么能我使用这个类来避免需要ScratchlessCat#Scratch
。
猫的例子是LSP的一个很好的例证。在了解LSP时,我曾惊讶于SO和其他网站上有多少不好的例子以及有多少误解。 – SteveT