当前位置: 首页 > 知识库问答 >
问题:

理解liskov替换原理需要清晰

卢晟
2023-03-14

LSP定义指出,如果S是T的子类型,则程序中T类型的对象可以替换为S类型的对象,而不改变该程序的任何期望属性。

  1. 子类型中的前提条件不能加强

例如,我有下面的类,这是违反(在子类型中不能加强前提条件)。我正试图把我的头绕在这上面,请有人提供一个好的例子来理解它。

Class Switch:
   def __init__(self,ip,dc):
       self.ip=ip
       self.dc=dc

class CiscoSwitch(Switch):
   def __init__(self,ip,dc,zone):
       super().__init__(ip,dc)
       self.zone=zone

class JuniperSwitch(Switch):
   def __init__(self,ip,dc,zone):
       super().__init__(ip,dc)
       self.zone=zone

共有1个答案

盖马鲁
2023-03-14

LSP原则通过接口工作,即对象/值中的公共内容。在Python中,您拥有公共的属性和方法,因此,如果您要实现一个接口,您必须遵守它。在您的示例中,Switch类仅定义与其属性相关的接口,即它具有ipdc字段。由于您正在CiscoSwitchJuniperSwitch中调用super,因此它们都有这些字段,因此实现了开关的“接口”,并且可以替换它。

现在,让我们来解决您提到的条件:

  1. 先决条件不能在子类型中得到加强

假设您有一个带有为形状着色的方法的接口,该方法只接受十六进制颜色(“123456”)或rgb颜色((123124125))。假设您创建了一个实现此接口的类矩形,但它只接受rgb颜色。你在强化先决条件。如果代码中有这一行:generic\u shape。颜色(“123456”)

无法替换其中的矩形,因此正在破坏LSP。

一个典型的例子是,对于不应返回None的方法,返回None。假设在Shape界面中,您有一个getSide方法,并且您创建了一个Circle类,在实现此方法时,您返回None。这打破了调用者的预期,并可能导致意外错误:

side = generic_shape.get_side() # suppose it is a circle
scaled_side = side * 2 # you get an error

在我看来,这一点更复杂,因为很难让它明确。我能想到的唯一一个例子是将属性保持为非Null,假设在您的示例中,您有一个不使用IP的交换机(可能使用MAC addr),如果交换机接口期望IP字段不应为None,您的MAC交换机将代理此接口。

我希望它能有所帮助!

 类似资料:
  • 我试图通过反复阅读维基百科条目来确定我对上述原则的理解。 撇开仍然让我悲伤的协变和逆变的概念不谈,wikipedia还提到超类型的不变量必须保留在子类型和历史约束或历史规则中。基于最后两个概念,我提出了一个小例子: 所以我的问题是:基于上述两个概念,我用这个例子是否违反了原则?若否,原因为何? 事先非常感谢。

  • 在创建我的班级结构时,我努力坚持利斯科夫替代原则。我想在Day类中存储一组日历项。需要有几种不同类型的日历项,例如: 任命项目 备注项目 轮换项目 它们都共享一些抽象基类CalendarItem中的常见功能: 但例如RotaItem有一些额外的功能: 其他类也添加了自己的逻辑等。 我有一组CalendarBaseItem用于我的日课: 但在回顾这一点时,我可以看到我正在打破LSP原则,因为我必须检

  • 我试图理解Liskov替换原理,我有以下代码: 我不确定这是否违反了它。原理是,如果你有一个类S的对象,那么你可以用另一个类T的对象来代替它,其中S是T的一个子类。但是,如果我写了 这当然会产生编译错误,因为Vehicle类没有openDoor()方法。但这意味着我不能用它们的父类Vehicle替换VehicleWithDoors对象,这似乎违反了原则。那么这个代码是否违反了它?我需要一个好的解释

  • 来自维基百科, Liskov的行为子类型概念定义了对象的可替代性概念;也就是说,如果S是T的子类型,则程序中T类型的对象可以替换为S类型的对象,而不改变该程序的任何期望属性(例如正确性)。 假设以下类层次结构: 基本抽象类-。它有一个只读属性,在后继程序中被重写。 基类的继承者-,它重写并返回灰色。 Cat的继任者-,它覆盖并返回带条纹的。 然后我们声明一个方法,参数类型为(不是)。 向该方法发送

  • Liskov替换原则对派生类中的方法签名施加的规则之一是: 子类型中方法参数的对比。 如果我理解正确的话,就是说派生类的重写函数应该允许逆变参数(超类型参数)。但是,我不明白这条规则背后的原因。由于LSP主要讨论动态地将类型绑定到这些子类型(而不是超类型)以实现抽象,所以允许超类型作为派生类中的方法参数对我来说是相当混乱的。我的问题是: 为什么LSP允许/需要派生类的重写函数中的逆变参数? 对比方