1

读完这篇文章后,我想我主要了解 LSP 和大多数示例,但我不能说我是 100% 确定从我对许多继承示例的经验来看,因为似乎很多示例确实违反了 LSP,而且似乎很难当覆盖行为时不要。

例如,考虑以下简单的继承演示,取自Head First Object Oriented Analysis & Design。他们是否违反了 Jet 子类的 LSP?

public class Airplane {
  private int speed;

  public void setSpeed(int speed) {
    this.speed = speed;
  }
  public int getSpeed() {
    return speed;
  }
}

public class Jet extends Airplane {
  private static final int MULTIPLIER=2;

  /**
   * The subclass can change behaviour of its superclass, as well as call the
   * superclass's methods. This is called overriding the superclass's behaviour
   */
  public void set setSpeed(int speed) {
    super.setSpeed(speed * MULTIPLIER);
  }

  public void accelerate() {
    super.setSpeed(getSpeed() * 2);
  }
}

使用对基类 Airplane 实例的引用的客户端在设置速度后可能会惊讶地发现它在传递一个 Jet 对象的实例后是预期速度的两倍。Jet 是不是改变了 setSpeed() 方法的后置条件,从而违反了 LSP?

例如

void takeAirplane(Airplane airplane) { 
    airplane.setSpeed(10);
    assert airplane.getSpeed()==10;
}

如果 takeAirplane 传递了对 Jet 对象的引用,这显然会失败。在我看来,在“覆盖超类的行为”时很难不违反 LSP,但这是继承的主要/理想特性之一!

有人可以解释或帮助澄清这一点吗?我错过了什么吗?

4

1 回答 1

1

根据维基百科

[里氏替换原则]指出,在计算机程序中,如果 S 是 T 的子类型,则类型 T 的对象可以用类型 S 的对象替换(即,类型 S 的对象可以替换类型 T 的对象)更改该程序的任何理想属性(正确性、执行的任务等)。

在 Jet 的情况下,它的速度是两倍的速度违反了 LSP——它没有满足后置条件setSpeed(getSpeed(x))==x

Liskov 替换原则说,只要程序的正确性没有改变,就可以修改派生类中的行为。它对您在派生类中所做的更改施加了限制。

于 2014-06-26T10:59:54.600 回答