1

我有一个模型抽象类,它声明了一个项目列表。抽象有两个抽象类。一种是您可以将新项目添加到列表中,另一种是根本不使用该列表,而是遵循模型抽象类的其他行为。

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

在这种情况下我可以违反LSP(Liskov 替换原则)吗?或者有没有办法解决这个问题?

4

3 回答 3

1

我认为你会违反 LSP。

LSP 的 Wikipedia 页面(始终是您的朋友;):

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

“行为子类型是比类型论中定义的函数的典型子类型更强大的概念,它仅依赖于参数类型的逆变和返回类型的协变。行为子类型通常是微不足道的不可判定的”

看起来与您的情况相似:

“一个违反 LSP 的典型例子是从 Rectangle 类派生的 Square 类,假设宽度和高度都存在 getter 和 setter 方法。Square 类总是假设宽度与高度相等。如果使用 Square 对象在期望 Rectangle 的上下文中,可能会发生意外的行为,因为 Square 的尺寸不能(或者不应该)独立修改。这个问题不容易解决:如果我们可以修改 Square 类中的 setter 方法,以便它们保留 Square 不变量(即,保持维度相等),那么这些方法将削弱(违反)Rectangle setter 的后置条件,即维度可以独立修改。违反 LSP 的情况,比如这个,可能会也可能不会在实践中成为问题”

于 2011-12-22T10:45:21.753 回答
0

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

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

所以你必须把一个方面变成一个接口,并从实现一个或多个接口的抽象类扩展。

当 Square 从 Rectangle 扩展并实现 WidthEqualsHeight 时,LSP 成立。

于 2011-12-22T10:53:06.307 回答
0

从来没有学过 LSP 但我不好说

必须强制转换始终是糟糕(不太理想)OO 设计的标志。

如果你想要一个模型,你也可以设置东西,然后将它声明为正确的模型

Java 集合 API 也是如此

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

是可以工作但写得不好的代码吗

本来应该是

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

使用您想要的特定类型

于 2011-12-22T10:39:04.437 回答