gpt4 book ai didi

java - 如何避免违反里氏替换原则 (LSP)?

转载 作者:太空狗 更新时间:2023-10-29 22:54:04 26 4
gpt4 key购买 nike

我的处境与Steve McConnell's 非常相似在Code Complete中有提到。只有我的问题是基于 Vehicles 而 Trike 恰好是根据法律属于 Cars 类别。到目前为止,汽车只有四个轮子。无论如何,我的域都不必要地复杂,因此很容易坚持使用下面的猫示例。

Be suspicious of classes that override a routine and do nothing inside the derived routine This typically indicates an error in the design of the base class. For instance, suppose you have a class Cat and a routine Scratch() and suppose that you eventually find out that some cats are declawed and can't scratch. You might be tempted to create a class derived from Cat named ScratchlessCat and override the Scratch() routine to do nothing. This approach presents several problems:

It violates the abstraction (interface contract) presented in the Cat class by changing the semantics of its interface.

This approach quickly gets out of control when you extend it to other derived classes. What happens when you find a cat without a tail? Or a cat that doesn't catch mice? Or a cat that doesn't drink milk? Eventually you'll end up with derived classes like ScratchlessTaillessMicelessMilklessCat.

Over time, this approach gives rise to code that's confusing to maintain because the interfaces and behavior of the ancestor classes imply little or nothing about the behavior of their descendants.

The place to fix this problem is not in the base class, but in the original Cat class. Create a Claws class and contain that within the Cats class. The root problem was the assumption that all cats scratch, so fix that problem at the source, rather than just bandaging it at the destination.

根据他上面的伟大著作中的文字。跟风不好

父类不必是抽象的

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 不应在其 API 中定义公共(public) scratch 方法。第一步是考虑为什么首先要定义 scratch。也许猫在受到攻击时会抓挠;否则它们会发出嘶嘶声或逃跑。

public class Cat extends Animal {
private Claws claws;

public void onAttacked(Animal attacker) {
if (claws != null) {
claws.scratch(attacker);
}
else {
// Assumes all cats can hiss.
// This may also be untrue and you need Voicebox.
// Rinse and repeat.
hiss();
}
}
}

现在您可以用任何 Cat 子类替换另一个子类,它会根据它是否有爪子正确运行。您可以定义一个 DefenseMechanism 类来组织各种防御,例如 ScratchHissBite 等。

关于java - 如何避免违反里氏替换原则 (LSP)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10778354/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com