语言-编程原则SOLID-LSP

Liskov Substitution Principle Liskov替代原则

A great example illustrating LSP (given by Uncle Bob in a podcast I heard recently) was how sometimes something that sounds right in natural language doesn't quite work in code.

In mathematics, a Square is a Rectangle. Indeed it is a specialization of a rectangle. The "is a" makes you want to model this with inheritance. However if in code you made Square derive from Rectangle, then a Square should be usable anywhere you expect a Rectangle. This makes for some strange behavior.

 

在数学中,Square是一个矩形。 事实上,这是一个矩形的专业化。 “是”使你想用继承来建模。 然而,如果你在Square中的代码是从矩形派生的,那么一个Square应该可以在任何你期望的矩形中使用。 这使得一些奇怪的行为。

 

Imagine you had SetWidth and SetHeight methods on your Rectangle base class; this seems perfectly logical. However if your Rectangle reference pointed to a Square, then SetWidth and SetHeight doesn't make sense because setting one would change the other to match it. In this case Square fails the Liskov Substitution Test with Rectangle and the abstraction of having Square inherit from Rectangle is a bad one.

 

想象一下你的Rectangle基类有SetWidth和SetHeight方法; 这似乎完全合乎逻辑。 但是,如果您的Rectangle引用指向Square,则SetWidth和SetHeight没有意义,因为设置一个会更改另一个以匹配它。 在这种情况下,Square使用矩形失败了Liskov替换测试,并且从矩形继承的Square的抽象是不好的。

 

Robert Martin has an excellent paper on the Liskov Substitution Principle. It discusses subtle and not-so-subtle ways in which the principle may be violated.

 

Some relevant parts of the paper (note that the second example is heavily condensed):

罗伯特马丁有关里斯科替代原则的优秀论文。 它讨论了可能违反原则的微妙和不那么微妙的方式。

 

论文的一些相关部分(请注意第二个例子严重缩写):

One of the most glaring violations of this principle is the use of C++ Run-Time Type Information (RTTI) to select a function based upon the type of an object. i.e.:

这个原则最明显的违反之一是使用C ++运行时类型信息(RTTI)来根据对象的类型选择函数。即:

[...] Imagine that one day the users demand the ability to manipulate squares in addition to rectangles. [...]

 

Clearly, a square is a rectangle for all normal intents and purposes. Since the ISA relationship holds, it is logical to model the Square class as being derived from Rectangle. [...]

想象一下,有一天用户需要能够操纵矩形之外的方块。[...]

 

显然,正方形对于所有正常的意图和目的都是矩形。 由于ISA关系成立,将Square类建模为从矩形派生是合乎逻辑的。[...]

Square will inherit the SetWidth and SetHeight functions. These functions are utterly inappropriate for a Square, since the width and height of a square are identical. This should be a significant clue that there is a problem with the design. However, there is a way to sidestep the problem. We could override SetWidth and SetHeight [...]

Square将继承SetWidth和SetHeight函数。 这些函数完全不适合Square,因为Square的宽度和高度是相同的。 这应该是设计中存在问题的重要线索。 但是,有一种方法可以避开这个问题。 我们可以覆盖SetWidth和SetHeight [...]

If we pass a reference to a Square object into this function, the  Square object will be corrupted because the height won’t be changed. This is a clear violation of LSP. The function does not work for derivatives of its arguments.

如果我们将一个Square对象的引用传递给这个函数,Square对象将会被破坏,因为高度不会被改变。 这明显违反了LSP。 该函数不适用于其参数的派生。

 

 

Bad example

Good example

public class Bird{
    public void fly(){}
}
public class Duck extends Bird{}
public class Ostrich extends Bird{}

 

public class Bird{

}

public class FlyingBirds extends Bird{

    public void fly(){}

}

public class Duck extends FlyingBirds{}

public class Ostrich extends Bird{}

 

 

总结一句话:

我们在继承父类的方法的时候,要考虑该父类中的方法是不是适合子类,如果适合继承,如果不适合应该继承其他类,或者在父类的基础上再派生出一个类。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值