在这种情况下我可以违反LSP(Liskov替换)吗?

时间:2011-12-22 10:15:20

标签: java inheritance liskov-substitution-principle

我有一个模型抽象类,它声明了一个项目列表。摘要有两个抽象类。可以在其中添加新项目到列表中的项目以及根本不使用该项目列表的项目,但除此之外还要遵守模型抽象类的其他行为。

我声明了两种方法来添加和删除列表中的项目。显然,每当我想使用这些方法时,我需要使用它的子类来构建我的模型摘要。

在这种情况下,我可以违反LSP (Liskov substitution principle)吗?或者有解决这个问题的方法吗?

3 个答案:

答案 0 :(得分:1)

我认为你会违反LSP。

来自Wikipedia page for LSP(总是你的朋友;):

"更正式地说,Liskov替换原则(LSP)是子类型关系的特定定义,称为(强)行为子类型"

&#34;行为子类型比类型理论中定义的函数的典型子类型更强大,它仅依赖于参数类型的逆变量和返回类型的协方差。行为子类型通常是非常不可判断的<#34;

看起来与您的情况类似:

&#34;违反LSP的典型示例是一个Square类,它派生自Rectangle类,假设宽度和高度都存在getter和setter方法。 Square类总是假设宽度等于高度。如果在期望Rectangle的上下文中使用Square对象,则可能会发生意外行为,因为Square的尺寸不能(或者不应该)独立修改。这个问题不容易修复:如果我们可以修改Square类中的setter方法以保持Square不变量(即保持尺寸相等),那么这些方法将削弱(违反)Rectangle setter的后置条件,声明尺寸可以独立修改。像这样违反LSP,在实践中可能会或可能不会成为问题&#34;

答案 1 :(得分:0)

从未研究过LSP,但生病了吗

不得不进行施法总是表明糟糕(不太理想)的OO设计。

如果您想要一个可以设置的模型,那么将其声明为正确的模型

与Java Collection API相同

Collection coll = new ArrayList();
((List) coll).set(3,"sdf");

代码是否有效,但编写得很糟糕

应该有背景

List coll = new ArrayList();
coll.set(3,"sdf");

根据需要使用特定类型

答案 2 :(得分:0)

我理解LSP,但这里可能是问题解决了java具有单一继承和多个接口的设计原因。

一个班级可以扩展另一个班级。在C ++中,情况并非如此,超类中可能存在冲突的名称。多重继承也给出了一些理论类型问题。

因此,您必须将一个方面转换为接口,并从实现一个或多个接口的抽象类扩展。

当Square从Rectangle扩展并实现WidthEqualsHeight时,LSP保持。