抽象属性是否违反Liskov替换原则?

时间:2011-06-06 18:35:22

标签: java oop liskov-substitution-principle

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

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。我的问题是,这是否违反Liskov替代原则,该原则指出:

  

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

4 个答案:

答案 0 :(得分: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实例时现有代码会中断。

答案 1 :(得分:4)

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

答案 2 :(得分:1)

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

现在,当程序员调用所谓的“Liskov替换原则”时,他们并没有在学术意义上谈论它。我们必须以一种非正式的,粗俗的,卑鄙的方式使用它。

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

答案 3 :(得分:0)

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

如果合同规定“ getSpecialTreatment”始终返回true,则您将在派生类中违反此规定。

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

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