如何避免破坏里氏替换原理(LSP)?
我的情况与史蒂夫·麦康奈尔(Steve McConnell)在《代码完成》(Code Complete)中提到的情况非常相似。只是我的问题是基于车辆和三轮车恰好是法律属于汽车类别。到目前为止,汽车有四个轮子。无论如何,我的领域是不必要的复杂,所以很容易坚持下面的猫的例子。
对重写例程且在派生例程中不执行任何操作的类持怀疑态度 这通常表示基类设计中存在错误。例如,假设你有一个类Cat和一个例行的Scratch(),并假设你最终发现一些猫是被禁止的,不能抓挠。您可能想创建一个名为 ScratchlessCat 的 Cat 派生类,并重写 Scratch() 例程以不执行任何操作。这种方法存在几个问题:
它通过更改其接口的语义违反了 Cat 类中呈现的抽象(接口协定)。
此方法在扩展到其他派生类时会很快失控。当你发现一只没有尾巴的猫时会发生什么?还是一只不抓老鼠的猫?还是一只不喝牛奶的猫?最终,你最终会得到像ScratchlessTaillessMicelessMilklessCat这样的派生类。
随着时间的推移,这种方法会产生令人困惑的代码,因为祖先类的接口和行为很少或根本没有暗示其后代的行为。
解决此问题的位置不在基类中,而是在原始 Cat 类中。创建一个 Claws 类,并将其包含在 Cats 类中。根本问题是假设所有的猫都抓挠,所以在源头上解决这个问题,而不仅仅是在目的地包扎它。
根据他上面的伟大书中的文字。以下不好
父类不必是抽象的
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