8

假设我有一个抽象类,例如:

public abstract class Pet {
    private final String name;
    public Pet(String name) { 
        this.name = name 
    };

    public abstract boolean getsSpecialTreatment();
}

public final class Dog extends Pet {
    @Override public boolean getsSpecialTreatment() { return true; }
}

public final class Cat extends Pet {
    @Override public boolean getsSpecialTreatment() { return false; }
}

我的程序会Pet根据是否设置特殊处理标志来区别对待 s。我的问题是这是否算作违反了 Liskov 替代原则,该原则指出:

[...] 在计算机程序中,如果 S 是 T 的子类型,那么 T 类型的对象可以被 S 类型的对象替换 [...]而不会改变该程序的任何期望属性(正确性,执行的任务), ETC。)。

4

4 回答 4

6

在这种情况下,这些类的用户可能会写:

...
if (pet.getsSpecialTreatment()) {
    // special treatment
    ...
} else {
    // normal treatment
    ...
}
...

此代码适用于这两种情况,因此您不会违反 LSP。但是,如果你有

public class UnknownAnimal extends Pet {
    @Override public boolean getsSpecialTreatment() {
        throw new UnsupportedOperationException("Unknown species"); 
    }
}

那么您将违反 LSP,因为现有代码在使用UnknownAnimal实例时会中断。

于 2011-06-06T19:04:48.303 回答
4

不会。程序中对该方法的任何使用都将基于返回值做出后续决策,就像任何其他方法一样。由于该方法存在的本质,任何程序都不应该对其结果做出假设。因此,此方法返回的值的变化不应该改变程序的属性。

于 2011-06-06T19:05:13.833 回答
1

首先,强烈反对你对猫的歧视!

现在,当程序员调用所谓的“里氏替换原则”时,他们并不是真正在谈论它的学术意义。我们一定是在某种非正式的、粗俗的、卑鄙的意义上使用它。

那是什么意思?我发现它只不过是要求子类必须符合超类设定的合同。所以真的很无趣。人们引用这句话只是为了狂热。

于 2011-06-06T19:33:13.670 回答
0

这取决于合同。也就是说,使用您的类的代码必须获得一致的行为,无论它使用的是什么类型的派生。

如果合同规定“getSpecialTreatment”总是返回 true,那么您将在派生类中违反这一点。

如果合同规定“getSpecialTreatment”返回一个布尔值确定 blabla.,那么您没有违反 LSP。

如果您引入了基类中不存在的附加约束,则可能违反 LSP。

于 2018-10-11T09:33:07.290 回答