IS-A和Liskov替代原则之间的区别?

问题描述 投票:5回答:2

我只是想知道IS-A(UML术语和OOP)和Liskov替换原则(LSP)之间是否存在差异?

实际上,两者都在谈论继承。那么实践中的主要区别是什么?

oop inheritance solid-principles liskov-substitution-principle
2个回答
8
投票

这两个术语最终都描述了相同的“概念”。

Liskov替换原则告诉您:当类型B的某个对象的每个和任何用法都可以用类型C的对象替换时,类B(基础)和C(子)之间的继承关系是合理的。

这意味着:B定义了API和公共合同--C也必须维护这些属性!

并且IS-A相同:C的某个对象也是B.

“差异”是:LSP为您提供可以检查的确切规则。而IS-A更像是一种“观察”或意图表达。比如:你表示你希望C级-A B级。

换句话说:当您不知道如何正确使用继承时,IS-A无法帮助您编写正确的代码。 LSP清楚地告诉你类似的东西:

class Base { int foo(); }
class Child extends Base { @Override double foo(); }

是无效的。根据LSP,您只能扩展方法参数,并限制返回值。

int iValue = someBase.foo();

不能替代

int iValue = someChild.foo();

因为foo()方法的结果扩大了。

最后的想法是:很多人认为C IS-A B与写下Child extends Base是一样的。是。但这只告诉编译器C扩展B.这并不意味着你在C中使用的方法将遵循LSP,从而将C转换为B的真实有效后代。

C IS-A B需要的不仅仅是“C延伸B”。要真正有效,LSP必须坚持!


0
投票

Is-A / Has-A是否使用继承。 laserCat是一种激光,还是应该只有激光场?如果以某种方式使用继承,LSP是一个需要注意的特定问题。

继承的好用是动物a1;使用a1.speed()(*)指向猫或狗。 LSP表示Cat和Dog的速度功能需要使用相同的单位。同样地,a1.setWeight for Cats不允许负权重,但Dogs将它们更改为0. LSP是关于你可以调用任一函数时的一致性。实际上很明显,如果你已经知道动物a1;诀窍,这很难。

相比之下,假设你有独立的猫和狗。如果真实地以不同的方式测量速度,那么让Cats使用公制并且Dogs是英语就可以了。如果Cats and Dogs从Animal继承,但你从不使用“a1 = Cat或Dog”技巧,它仍然没问题。 c1.speed()肯定是公制的,d1.speed()显然是每小时英里数。但是如果你有动作animalRace(动物a1),你就有问题了。

差异也是基调。对于刚开始的人来说,Is-a / has-a是一个简单的建议。 LSP来自一篇为博士学位撰写的30年前的论文。它使用的方程适用于毕业生Com Sci专业。它使用Pre和Post条件,这些条件是常见的,众所周知的术语。 “替换”是一个很好的数学术语,但今天我们只是说“将指向任何子类的基类”。

(*)更详细:我们有超类Animal,以及Cat和Dog的子类。 Animal具有存根速度功能,Cat和Dog各自覆盖它。 a1.speed()查找正确的。一个真实的例子是动物阵列,它真正拥有猫和狗。或具有动物输入的功能,期待猫或狗。

(相同*)基类通常是抽象的 - 我们永远不会创建一个Animal对象。但是如果我们有一个Toaster超类和一个DeluxeToaster子类,那么诀窍就是一样的。任何采取烤面包机的东西都可以采取任何“是一个”烤面包机。

© www.soinside.com 2019 - 2024. All rights reserved.