问题标签 [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 回答
1454 浏览

.net - 我可以实现一系列可重用的测试来测试接口的实现吗?

我正在用 C# 编写一系列集合类,每个集合类都实现了类似的自定义接口。是否可以为一个接口编写一个单元测试集合,并在几个不同的实现上自动运行它们?我想避免每个实现的任何重复测试代码。

我愿意研究任何框架(NUnit 等)或 Visual Studio 扩展来完成此任务。


对于那些希望做同样事情的人,我发布了基于avandeursen 接受的解决方案的具体解决方案作为答案

0 投票
3 回答
98 浏览

oop - OO设计建模

当您有一个基类和两个扩展该基类的类并且只有一个派生类与另一个对象有关系时,如何对域进行建模。

例子:

这个模型是否违反了 Liskov 原则?我认为是因为与 class3 的这种关系,所以我们必须弄清楚如何在没有这种关系的情况下建模或将这种关系移动到 Base。如果我有一部分程序处理 Class2 来处理与 Class3 的关系,我无法使用基类而不强制转换为 class2。

这个想法对吗?

澄清...

让我们在学习模型中思考。我们有课程和课程班。我们还可以开设在线课程和预科课程。在presencial 课程中,我们可能会面临这种培训的费用。因此,成本只对现有环境有意义。CourseClasses 可以有范围日期或定量日期。

今天我有这个模型:

现在我必须处理成本,直到现在,presencial 课程对我来说并不重要,但现在,成本只对 presencial 环境有意义。

我的问题是:我需要处理成本模块中的 CourseClass 对象,因为我需要一些 courseClass 的东西,但是成本的关系与 RangeCourseClass 因为 QuantitativeCourseClass 对 prensecial 环境没有意义。

关于 liskov 的问题是关于如何说服我的团队对这个模型进行一些修改。

0 投票
3 回答
275 浏览

liskov-substitution-principle - 重写方法参数类型的缩小是否违反了 Liskov 替换原则?

我有这个代码:

我从 Entity 和 BaseCollection 类派生:

这是违反 Liskov 替换原则的一个例子吗?如果是,我该如何解决这个问题?

0 投票
2 回答
572 浏览

php - 代码是否符合 Liskov 的替换原则?

在升级之前,我正在 PHP5.4 上测试我现有的代码。我发现以下代码不再有效,因为 PHP 加强了它的继承模型。由于这种收紧,我一直在阅读SOLID,特别是Liskov 的替换原则(我是一名自学成才的程序员),这样我就可以改进我的代码,而不会受到未来的“收紧”的影响。

php 5.3 结果:

  • 不同的
  • 平等的

php 5.4 结果:

PHP 致命错误:A::equals() 的声明必须与 IComparable::equals(IComparable $other) 兼容

如果我这样编写代码,我可以避免 php5.4 错误:

但是该修复是否符合 Liskov 的替换原则,因为该函数显然不接受任何参数类型?如果没有,我如何编写一个可继承的函数来满足我的需要——比较相同类型的 2 个对象——并遵守良好的 OOD 原则?

0 投票
2 回答
320 浏览

oop - 面向对象方法的类型安全

我正在尝试考虑如何使用面向对象的方法正确解决这个问题。语言并不重要——我其实很想写代码,但我更关心的是一般原则。

我想实现一个字段:操作 +、-、* 和 / 操作的“数字”集合。此外,我希望能够实现更高的操作,例如 ^ 和循环查找,其中 (1) 不需要为给定字段定义,但如果需要,可以覆盖 (2),例如出于效率原因。

这就是问题所在。不好申报

因为我想要类型安全:不可能将有限域的成员添加到整数中。

也许我真正在寻找的是元对象或超级接口,或者将不同类联系在一起的东西(一个用于整数,一个用于 7-adics,一个用于有限域 F_4,等等)。或者也许有更好的东西。

NB 代码在答案中受到欢迎(甚至鼓励),如果它有启发性的话,但声明可能就足够了:大概这里的每个人都可以为至少几个领域写出明显的方法。


我将提到其他对我很重要但(显然)与主要 OO 问题无关的条件:我不希望字段元素携带它们的类型信息,而且我希望它们是轻量级的(因为我可能需要处理大型字段元素数组)。这些需求可能无法实现——尽管坦率地说,我更可能在这里放弃面向对象而不是效率。但是无论如何,我都会很感激答案,因为我有兴趣了解这些问题,即使除了手头的特定问题。

0 投票
2 回答
3272 浏览

java - 如何避免违反 Liskov 替换原则 (LSP)?

我的情况与Steve McConnell在 Code Complete 中提到的情况非常相似。只是我的问题是基于 Vehicles 的,而 Trike 恰好在法律上属于 Cars 类别。到目前为止,汽车有四个轮子。无论如何,我的域都是不必要的复杂,所以很容易坚持下面的猫示例。

对覆盖例程并且在派生例程内不执行任何操作的类保持怀疑 这通常表明基类的设计存在错误。例如,假设您有一个 Cat 类和一个例程 Scratch(),并假设您最终发现一些猫已经去爪并且不能抓挠。您可能很想创建一个从 Cat 派生的名为 ScratchlessCat 的类,并重写 Scratch() 例程以不做任何事情。这种方法存在几个问题:

它通过更改其接口的语义违反了 Cat 类中呈现的抽象(接口契约)。

当您将这种方法扩展到其他派生类时,这种方法很快就会失控。当你发现一只没有尾巴的猫时会发生什么?还是一只不会抓老鼠的猫?还是一只不喝牛奶的猫?最终你会得到像 ScratchlessTaillessMicelessMilklessCat 这样的派生类。

随着时间的推移,这种方法会产生难以维护的代码,因为祖先类的接口和行为对其后代的行为几乎没有暗示。

解决这个问题的地方不在基类中,而是在原始的 Cat 类中。创建一个 Claws 类并将其包含在 Cats 类中。根本问题是假设所有的猫都会抓挠,所以从源头解决这个问题,而不是在目的地包扎它。

根据上面他伟大著作的文字。跟风不好

父类不必是抽象的

派生类

现在他建议创建另一个类Claws,但我不明白如何使用这个类来避免需要ScratchlessCat#Scratch.

0 投票
3 回答
1600 浏览

oop - 替代(或改进)遭受 LSP 违规的状态模式

对于我们目前正在构建的发票系统,我很难理解基于状态的功能。该系统将支持发票的计算、人工审批、打印和存档。

起初我认为我们应该使用状态模式来对此进行建模。发票将是上下文,它将打印、归档等委托给其当前分配的状态。

但这显然是个坏主意,因为不同的状态(创建、批准、打印、存档)不应该支持相同的操作。例如,您不应该能够打印以前未经批准的发票。为不受支持的操作抛出异常将违反 LSP。我在这里找到了这个问题的一般描述。

有没有人有想法,如何适当地实施这个?


PS:我知道这听起来像是一些蹩脚的家庭作业,但事实并非如此;我需要这个用于现实世界的系统。

0 投票
3 回答
3744 浏览

design-patterns - Does Liskov Substitution Principle also apply to classes implementing interfaces?

1) Does LSP also apply to interfaces, meaning that we should be able to use a class implementing a specific interface and still get the expected behavior?

2) If that is indeed the case, then why is programming to an interface considered a good thing ( BTW- I know that programming to an interface increases loose coupling ), if one of the main reasons against using inheritance is due to risk of not complying to LSP? Perhaps because:

a) benefits of loose coupling outweight the risks of not complying to LSP

b) compared to inheritance, chances that a class ( implementing an interface ) will not adher to LSP are much smaller

thank you

0 投票
1 回答
131 浏览

c# - 在 LSP 的上下文中,如何确保继承类不会破坏基类契约?

在 C# 中 - 但它可能适用于其他语言 - 在LSP的上下文中,我如何确保从另一个(可变)继承的类不会违反原始合同?

例如:如果我有public,internalprotected属性设置器,则存在继承类会破坏原始合同的风险。这同样适用于virtual方法。

如果父类和继承类的所有者不是同一个人,则尤其如此,因为这可能会导致合同和原始开发人员的意图缺乏知识。

不变性是唯一的解决方案还是有其他一些方法?我倾向于认为继承对应于“表现得像”-关系而不是“是”-关系。这是一个正确的逻辑保障吗?

为了便于说明,这里有一个示例:

我注意到有关此主题的其他一些问题(例如此处),但我正在寻找通用解决方案或良好实践来避免提前面对这些问题。

0 投票
2 回答
449 浏览

design-patterns - Liskov 替换原则是否也适用于实现接口的类?

LSP 声明类应该可以替代它们的基类,这意味着派生类和基类在语义上应该是等价的。

但是 LSP 是否也适用于实现接口的类?换句话说,如果一个类实现的接口方法在语义上与用户期望的不同,这是否会被视为违反 LSP?

谢谢