问题标签 [liskov-substitution-principle]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
4 回答
651 浏览

java - Java 异常层次结构背后的基本原理

我发现 Java 的异常层次结构令人困惑。Throwable分为Errorand ExceptionRuntimeException继承自Exception

  1. Error是未经检查的异常。为什么不Error继承RuntimeException呢?

  2. Exception是一个检查异常。RuntimeException是一个未经检查的异常,但它继承自Exception. 这不违反里氏替换原则吗?

Throwable如果分为Exception(checked) 和RuntimeException(unchecked) 并Error继承自 ,岂不是更有意义RuntimeExeption

0 投票
2 回答
266 浏览

c# - 等级制度违反了 Liskov - 那又怎样?

我使用的 API 违反了 Liskov 替换原则:它抛出了自己的扩展 Exception 的 Exception 类型,但将来自基类的异常消息放在新的 ErrorCode 字段中,并将自己的(无用的)消息放在 Message 字段中。因此,要显示正确的消息,我需要将异常转换为 DerivedException 类型并使用 ErrorCode 字段。如果我将其视为异常对象,则会收到错误消息。

现在这在风格上让我感到厌烦,但它很容易解决:我可以捕获 DerivedException 并按照程序员的意图使用它。所以我的问题是:Liskov 原则有什么大不了的?人们使用违反原则的层次结构可能会遇到哪些实际问题?

0 投票
18 回答
11369 浏览

java - 从具体类继承的任何好的例子?

背景:

作为一名 Java 程序员,我广泛地从接口继承(更确切地说:实现),有时我设计抽象基类。但是,我从来没有真正觉得需要子类化一个具体(非抽象)类(在我这样做的情况下,后来证明另一种解决方案,例如委托会更好)。

所以现在我开始觉得从具体类继承几乎没有合适的情况。一方面,对于非平凡类而言,里氏替换原则(LSP) 似乎几乎不可能满足;这里的许多其他问题似乎也反映了类似的观点。

所以我的问题:

在哪种情况下(如果有的话)从具体类继承实际上是有意义的?您能否给出一个从另一个具体类继承的类的具体真实示例,您认为这是给定约束的最佳设计?我对满足 LSP 的示例(或满足 LSP 似乎不重要的示例)特别感兴趣。

我主要有 Java 背景,但我对任何语言的示例都感兴趣。

0 投票
1 回答
80 浏览

design-patterns - 为了绑定而破坏LSP可以吗?

有些事情告诉我,我可能会因为问这个而被处以私刑。对于事先冗长的描述,我们深表歉意。

我正在研究 Silverlight 4 项目中的一个角落案例。本质上,我正在构建的是一个自定义表单构建器。

一个表单可能有几个字段,这些字段可能是不同类型的(文本、整数、电子邮件等)。现在,所有这些类型都扩展了Field类,但在文本字段的情况下可能具有其他属性,例如长度。

我有能力从FieldViewModels我的FormFieldsManagementViewModel. 所以到目前为止,这都是非常标准的东西。

现在,UserControl... DataTemplateSo , to clarify, the UserControlhas a SingleLineTextTemplateproperty which will be shown when a SingleLineTextFieldViewModelis selected but when an EmailFieldViewModelis selected, the EmailFieldTemplateis shown. SingleLineTextFieldViewModel和继承EmailFieldViewModelFieldViewModel

当我在每个模板中声明绑定时,我的问题就出现了。FieldViewModel设置基类的属性是非常有效的(恕我直言)IsRequired,但我也有与 .的Length 属性匹配的Position绑定。所以我依赖于具体类的扩展接口而不仅仅是类。LengthSingleLineTextTemplateSingleLineTextFieldViewModelFieldViewModel

我应该指出,在我继续说这有效之前。我不确定它会,现在确实如此,我不确定它应该,..或者我什至应该这样做。

我这样做只是为了绑定,并且没有绑定到动态对象和/或DataTemplateSelectorSilverlight 中没有绑定。

显然,在绑定场景中SingleLineTextFieldViewModel不能替代它的基类。我的问题是,因为我并没有真正在代码中使用这些对象,而是在标记中,..这仍然被认为是不好的做法吗?

提前非常感谢。

0 投票
2 回答
1582 浏览

liskov-substitution-principle - 了解 Liskov 和 OCP 之间的关系

我正在巩固我对 Liskov Substitutional Principal 和 Open Close Principal 之间关系的理解。如果有人能证实我的推论并回答我下面的问题,那就太好了。

我有以下课程。如您所见,B它派生自A并覆盖该DisplayMessage函数以改变行为。

现在在我的引导程序中,ShowClassTypeis期待一个类型的对象,A它应该有助于写出它是什么类类型。然而B,它违反了 LSP,所以当它的DisplayMessage函数被调用时,它会打印一条完全出乎意料的消息,并且本质上会干扰ShowClassType.

所以我的问题是,我的结论是否正确,ShowClassType因为现在 B 型可以进入并更改该方法的预期功能,它不再关闭以进行修改(即确保它保持它的预期的行为,你必须改变它,以便它首先检查以确保我们只使用原始 A 对象)?

或者,相反,这只是一个很好的例子来表明它ShowClassType是封闭的,并且通过传入派生类型(尽管 LSP 违反了)我们已经扩展了它的意图?

最后,如果基类不是抽象的,在基类上创建虚函数是不好的做法吗?通过这样做,我们不只是在邀请派生类违反 Liskov Substitution 原则吗?

干杯

0 投票
1 回答
221 浏览

gwt - GWT 的 ActivityMapper 是否违反了 Liskov 替换原则?

在我的 GWT 应用程序中,我有一个像这样的类:

ActivityMapper、Activity 和 Place 对象是框架的一部分,界面暗示这就是它的用途。

但是,根据Liskov 替换原则,接受类型但对子类进行类型检查以推断要采取什么行动的方法违反了该原则。

GWT 的 ActivityMapper 接口本质上是否鼓励违反 LSP?或者是否有另一种符合 LSP 的方法来编码我没有想到的方法?

0 投票
2 回答
1093 浏览

liskov-substitution-principle - Liskov 替换原则 - 覆盖方法示例

假设我们有这个非常简单的类:

这个例子会违反 LSP 吗?如果是这样,你能给我一个不违反原则并使用不同实现的例子吗?

这个如何:

据我了解,使用变量“变量”会导致更强的前提条件,因此它违反了 LSP。但是我不完全确定在使用多态性时如何遵循 LSP。

0 投票
3 回答
666 浏览

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

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

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

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

0 投票
1 回答
407 浏览

python - 类继承:构造函数应该兼容吗?多重继承的情况?

面向对象编程的推荐原则之一是Liskov 替换原则:子类的行为方式应与其基类相同(警告:这实际上不是对 Liskov 原则的正确描述:参见 PS) .

是否建议它也适用于构造函数?我主要考虑 Python 及其__init__()方法,但这个问题适用于任何具有继承的面向对象语言。

我问这个问题是因为有时从一个或多个提供一些不错的默认行为的类继承子类很有用(比如在 Python 中从字典继承,因此obj['key']适用于新类的对象)。然而,允许子类完全像字典一样使用并不总是自然或简单的:构造函数参数只与特定的用户子类相关(例如,表示一组串行端口的类)有时会更好可能想表现得像一本字典ports['usb1']是 USB 端口 #1 等)。对于这种情况,推荐的方法是什么?拥有与其基类完全兼容的子类构造函数,并通过采用简单、用户友好参数的对象工厂函数生成实例?还是简单地编写一个类构造函数,其参数集不能直接提供给其基类的构造函数,但从用户的角度来看哪个更合乎逻辑?

PS:我误解了上面的 Liskov 原则:Sven 在下面的评论指出子类的对象应该表现得像超类的对象(子类本身不必表现得像超类;特别是它们的构造函数没有具有相同的参数[签名])。

0 投票
1 回答
316 浏览

oop - 大富翁游戏——LSP OO原理

我正在设计一个大富翁游戏,同时也在阅读更多关于 OO 原则的内容。我正在阅读 LSP(Liskov 替换原则),发现要么我没有完全理解它,要么违反了它,应该改变我的设计。

(请注意:这个项目是个人的,只是为了好玩,所以我实际上并不关心代码的可维护性,但我只是要求个人教育和对 LSP 的理解)

让我从我迄今为止的设计开始:

BoardSpace是一个抽象基类,板上的每个“种类”空间都有一个子类。所以我有PropertySpace, TaxSpace, GoSpace, 等等。

BoardSpace有关于空间在板上的信息,还有一个抽象的void Land()方法,这样每个不同的空间在登陆时可以做不同的事情,因为它应该。这样,当我调用Land()当前BoardSpace对象时,它不需要关心或考虑其他任何事情,只做空间应该做的事情。对我来说,这是有道理的,听起来像是一个可行的解决方案。

但它似乎与 LSP 背道而驰,因为所有这些不同的Land()重写方法都会做完全不同的事情,就像我设计的那样。

还是我误解了 LSP?它与Land()“预期”或“描述”的工作方式有更多关系吗?在这种情况下,每个空间完全不同,所以没关系?或者它肯定是一种违规行为,我应该重新设计它?

附带问题:这会被认为是对继承的“滥用”还是对继承的良好利用?