里氏替换原则 - PHP面向对象编程(OOP)

PHP面向对象编程(OOP)用里氏替换原则来规范自己的行为

我的理解,父类有的,子类也得有。父类提供了地基,子类继承地基,继续建房子即可,玩玩不可在子类上取破坏父类提供的地基。

为什么叫里氏替换原则?

里氏替换原则在SOLID这五个设计原则中是比较特殊的存在:

  • 如果违反了里氏替换原则,不只是降低软件设计的优雅性,很可能会导致Bug
  • 只有里氏替换原则是以人名命令的

里氏替换原则译自Liskov substitution principle。Liskov是一位计算机科学家,也就是Barbara Liskov,麻省理工学院教授,也是美国第一个计算机科学女博士,师从图灵奖得主John McCarthy教授,人工智能概念的提出者。

里氏替换原则最初由Barbara Liskov在1987年的一次学术会议中提出,而真正正式发表是在1994年,Barbara Liskov 和 Jeannette Wing发表的一篇学术论文《A behavioral notion of subtyping》.

什么是里氏替换原则?

里氏替换原则在1994年Barbara Liskov 和 Jeannette Wing发表论文中的描述是:

If S is a declared subtype of T, objects of type S should behave as objects of type T are expected to behave, if they are treated as objects of type T

从字面上翻译:如果S是T的子类型,对于S类型的任意对象,如果将他们看作是T类型的对象,则对象的行为也理应与期望的行为一致。

而另一种关于里氏替换原则的描述为Robert Martin在《敏捷软件开发:原则、模式与实践》一书中对原论文的解读:子类型(subtype)必须能够替换掉他们的基类型(base type)。这个是更简明的一种表述。

如何理解里氏替换原则?

不管是Barbara Liskov论文中的表述,还是Robert Martin的解读,都是比较抽象的表达。要理解里氏替换原则,其实就是要理解两个问题:

  • 什么是替换?
  • 什么是与期望行为一致的替换(Robert Martin所说的“必须能够替换”)?

什么是替换

替换的前提是面向对象语言所支持的多态特性,同一个行为具有多个不同表现形式或形态的能力。

什么是与期望行为一致的替换?

在不了解派生类的情况下,仅通过接口或基类的方法,即可清楚的知道方法的行为,而不管哪种派生类的实现,都与接口或基类方法的期望行为一致。或者说接口或基类的方法是一种契约,使用方按照这个契约来使用,派生类也按照这个契约来实现。这就是与期望行为一致的替换。

违反里氏替换原则的危害

当我们违反了这一原则会带来有一些危害:

  • 反直觉。期望所有子类行为是一致的,但如果不一致可能需要文档记录,或者在代码跑失败后涨此知识;
  • 不可读。如果子类行为不一致,可能需要不同的逻辑分支来适配不同的行为,徒增代码复杂度;
  • 不可用。可能出错的地方终将会出错。

如何避免违反里氏替换原则

谈到如何避免,当然要基于里氏替换原则的定义,与期望行为一致的替换

  • 从行为出发来设计。在做抽象或设计时,不只是要从模型概念出发,还要从行为出发,比如一个经典的例子,正方形和长方形,从现实的概念中正方形是一个长方形,但是在计算其面积的行为上是不一致的。
  • 基于契约设计。这个契约即是基类方法签名、功能描述、参数类型、返回值等。在派生类的实现时,时刻保持派生类与基类的契约不被破坏。

参考文章

php

类中类外访问静态成员和普通成员 - PHP面向对象编程(OOP)

2022-8-25 17:27:46

php

self关键字详解(parent、static和this) - PHP

2022-8-26 17:37:19

⚠️
Npcink上的部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。
无意侵害您的权益,请发送邮件至 1355471563#qq.com 或点击右侧 私信:Muze 反馈,我们将尽快处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索