了解LSP

时间:2014-02-26 13:02:06

标签: oop liskov-substitution-principle

在阅读了这篇post后,我想我大部分都了解LSP和大部分的例子,但我不能说我对我的许多继承实例的经验100%肯定,因为它似乎有许多例子确实违反了LSP,并且在覆盖行为时似乎很难。

例如,考虑以下简单的继承演示,取自Head First Object Oriented Analysis & Design。他们是否违反了LSP子类的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?

E.g。

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

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

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

1 个答案:

答案 0 :(得分:1)

根据Wikipedia

  

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

对于Jet而言,它的速度是违反LSP的两倍 - 它失败了setSpeed(getSpeed(x))==x

的后置条件

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