Oop 理解LSP

Oop 理解LSP,oop,liskov-substitution-principle,Oop,Liskov Substitution Principle,读了这篇文章后,我认为我基本上理解了LSP和大多数示例,但我不能说我对许多继承示例的经验是100%肯定的,因为似乎许多示例确实违反了LSP,而且在重写行为时似乎很难不这样做 例如,考虑下面继承的简单示例,取自。他们在Jet儿童班违反LSP吗 public class Airplane { private int speed; public void setSpeed(int speed) { this.speed = speed; } public int getSpe

读了这篇文章后,我认为我基本上理解了LSP和大多数示例,但我不能说我对许多继承示例的经验是100%肯定的,因为似乎许多示例确实违反了LSP,而且在重写行为时似乎很难不这样做

例如,考虑下面继承的简单示例,取自。他们在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);
  }
}
使用对基类飞机实例的引用的客户机在设置速度后可能会惊讶地发现,在传递Jet对象的实例后,速度是预期速度的两倍。Jet不是在更改setSpeed()方法的post条件,从而违反了LSP吗

例如

如果向TakeAirport传递对Jet对象的引用,则显然会失败。 在我看来,“重写超类的行为”时很难不违反LSP,但这是继承的主要/可取的特性之一

有人能解释或帮助澄清这一点吗?我遗漏了什么吗?

根据

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

在喷气机的情况下,它的速度是LSP的两倍,这违反了后条件,即
setSpeed(getSpeed(x))==x


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

谢谢您的回答。所以,如果Jet违反了LSP,这难道不表明继承和LSP之间存在巨大的困难,几乎不兼容吗?如果一本编程设计书甚至不能给出一个不违背这个设计原则的例子,那还有什么希望呢?继承的一个基本驱动因素——覆盖父类的行为——是否与LSP的原则完全不一致?不,不一致。子类中的重写行为确实是OOP的一个基本部分。LSP是明智使用它的指南。好的,谢谢。你已经回答了我的第二个问题,但不是第一个问题,也就是说,这不说明不违反LSP的巨大困难吗?我要说的是,许多继承示例,类似于参考书中给出的上述示例,以类似的方式破坏LSP。因此,在我看来,学习面向对象编程基础知识的人被教导使用不正确的继承。
void takeAirplane(Airplane airplane) { 
    airplane.setSpeed(10);
    assert airplane.getSpeed()==10;
}