【问题标题】:How does LSP (Liskov Substitution Principle) worksLSP(里氏替换原则)如何工作
【发布时间】:2019-02-05 17:12:06
【问题描述】:

LSP(Liskov 替换原则)指出: 该原则规定,在不破坏应用程序的情况下,超类的对象可以被其子类的对象替换。

例如:

Vehicle BMW = new Car();

上述语句在内存级别是如何工作的(它是如何工作的)? 创建“汽车”类是为了满足汽车具有但一般车辆缺乏的特定行为。

如何将“BMW”对象引用到车辆类?

【问题讨论】:

  • 它不是BMW 对象,它是一个名为BMWVehicle 变量。
  • Car 可以是Vehicle,但Vehicle 不一定是Car,例如可以是Truck
  • 没关系,用简单的英语说汽车是交通工具时感觉很自然,这很明显。
  • 你能解释一下实例化类车辆变量但使用Car()的构造函数的现象吗?

标签: java object parent substitution


【解决方案1】:

简单地说,LSP 是关于您使用的变量和引用的可替代性。一个常见的例子是集合 api:

ArrayList<String> someList = new ArrayList<>();

这没关系,但假设我们有一个列表方法:

public void printList(LinkedList<String> printedList) { ... }

现在,我们不能将ArrayList&lt;String&gt; 传递给LinkedList&lt;String&gt; 参数,它们是不同的类型!但是,我们唯一需要的实际功能不是LinkedListArrayList 的特定怪癖,而只是List 本身的特定功能。所以我们用可替代的方式写这些

List<String> someList = new ArrayList<>(); //still an arraylist!

public void printList(List<String> printedList) { ... } //any list type

现在我们可以传递我们的参数,因为我们不会不必要地绑定到我们不需要功能的子类型。

就内存级别而言,这些对象仍然是堆内存中的相同对象,您只需将它们称为它们的超类型(实际上,如果您知道类型,您可以向下转换它们)。

因此,使用您的示例,您可能会遇到任何现有车辆都有颜色的情况。所以我们有方法:

public class Vehicle {

    public Color getColor() { ... }
    public void setColor(Color color) { ... }

}

在此过程中,Vehicle任何 子类将具有颜色方法,但不具有与 BMWCar 相关的更具体的方法。然而,这与继承比 LSP 更相关。

【讨论】:

  • 首先非常感谢您提供如此详细的回答。
  • 第二个是我刚开始学习 oop> 而我对类和对象的理解是这样的。类对对象就像数据类型对变量一样。非常简单,但是我们创建了一个子类来增强行为并更具体地处理某些事情。我无法理解的是,如果我们使用父类作为参考,那没关系,因为它很自然,但为什么我们使用子类的构造函数进行初始化。
  • 最后一个问题是:一个 LSP 的应用程序是假设我们有一个从 Media 类扩展的音频和视频对象列表,我们可以使用 Media 类引用从列表中检索对象,但首先会有是 Media 类中将缺少的某些属性或某些特定实例变量,我们将如何处理。
  • 简单的例子:List是一个抽象类型,不能被实例化(把它想象成一个“不完整”的类,把类想象成描述对象的“蓝图”,用对象是实际情况)。在这种情况下,我们为它提供了一个具体类型(ArrayList、LinkedList 等),它实现了任何缺失的行为。由于这个特定原因,new List&lt;&gt;() 是无效的 java。
  • 对于Media 示例,您可以使用instanceof 运算符来确定您正在使用的变量的类型。 someList instanceof ArrayList 将返回 true,与 List 比较时相同,但不是 LinkedList。一旦你用instanceof 确定了类型,你就可以简单地转换变量并将其视为子类((ArrayList&lt;String&gt;) someList).set(0, "test")
【解决方案2】:

LSP 表示当我们扩展一个类时,子类和超类之间的关系必须是IS A。在您的示例中,汽车 IS A 车辆。所以当 Car 类扩展 Vehicle 时,不会违反 LSP。

在内存级别,创建了一个 Car 对象,该对象由 Vehicle 引用。 BMW 引用将能够访问 Vehicle 的所有公共和受保护方法、实例变量。

【讨论】:

  • 但是使用构造函数 Car() 背后的含义是什么;
猜你喜欢
  • 2020-04-05
  • 2017-05-14
  • 1970-01-01
  • 1970-01-01
  • 2015-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多