【发布时间】:2012-05-28 00:59:18
【问题描述】:
我的情况与 Code Complete 中提到的 Steve McConnell's 非常相似。只有我的问题是基于 Vehicles 和 Trike 恰好是在法律上属于 Cars 类别。到目前为止,汽车有四个轮子。无论如何,我的域都是不必要的复杂,所以很容易坚持下面的猫示例。
对覆盖例程且内部不执行任何操作的类持怀疑态度 派生的例程 这通常表明设计中的错误 基类。例如,假设你有一个类 Cat 和一个 例程 Scratch() 并假设你最终发现一些 猫是去爪的,不能抓挠。您可能会想创建一个 从名为 ScratchlessCat 的 Cat 派生的类并覆盖 Scratch() 例行公事什么都不做。这种方法存在几个问题:
它违反了 Cat 中提出的抽象(接口契约) 类通过改变其接口的语义。
当您将这种方法扩展到其他方法时,它很快就会失控 派生类。当你发现一只没有尾巴的猫时会发生什么?或者一个 不会抓老鼠的猫?还是一只不喝牛奶的猫? 最终你会得到像这样的派生类 ScratchlessTaillessMicelessMilklessCat。
随着时间的推移,这种方法会产生令人困惑的代码 维护,因为祖先类的接口和行为 暗示他们后代的行为很少或根本没有。
解决这个问题的地方不在基类,而是在 原始的猫类。创建一个 Claws 类并将其包含在 猫科。根本问题是假设所有的猫都会抓挠, 所以要从源头上解决这个问题,而不是仅仅把它包扎起来 目的地。
根据上面他伟大的书中的文字。跟随不好
父类不必是抽象的
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。
【问题讨论】:
-
Cat 示例很好地说明了 LSP。在了解 LSP 的过程中,我惊讶于 SO 和其他网站上有多少糟糕的示例以及存在多少误解。
标签: java oop liskov-substitution-principle