• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • dedecms
  • ecshop
  • z-blog
  • UcHome
  • UCenter
  • drupal
  • WordPress
  • 帝国cms
  • phpcms
  • 动易cms
  • phpwind
  • discuz
  • 科汛cms
  • 风讯cms
  • 建站教程
  • 运营技巧
您的位置:首页 > CMS教程 >建站教程 > 分析PHP7.2忽略父类方法以及Liskov替换原则相关问题

分析PHP7.2忽略父类方法以及Liskov替换原则相关问题

作者:站长图库 字体:[增加 减小] 来源:互联网 时间:2022-04-29

站长图库向大家介绍了PHP7.2忽略父类方法,Liskov替换原则等相关知识,希望对您有所帮助

细说 PHP 7.2 子类覆盖方法省略参数类型功能以及 Liskov 替换原则

PHP 7.2 出来也有段时间了,关于新版本有什么新改进,只要你关心 PHP 的发展,应该都看过。这里只细说一个可能会有误解的新功能。

PHP 7.2 可以在当子类覆盖(override)父类方法的时候,忽略父类方法的定义的参数的类型(type hint):

class Foo{    public function bar(SomeClass $obj) {}}class Foobar extends Foo{    public function bar($obj) {} // 这在 PHP7.2 版本之前是会报错的}

我看有些网站介绍此功能的时候,说其目的是为了『方便重构。如果以后父类方法的参数类型变了,子类不用再全部换一遍』。听起来好像很有道理。按这说法,隐含的意思是:如果子类忽略了父类方法参数类型,被调用时还是会检查参数类型。实际情况是不是这样做一下实验就知道了:

<?phpclass Foo{}class Bar{    public function setFoo(Foo $foo)    {    }}class BarKid extends Bar{    public function setFoo($foo)    {    }}$kid = new BarKid;$kid->setFoo('I am a string!');

如果上面的说法是对的,setFoo 接受字符串参数的时候就应该报错,然而上面代码在 7.2 下并没有任何报错信息,但如果子类的 setFoo 方法加上了参数类型,就会立马报错了。记住网上很多说法都不可信,除了我这个小站……

上面的实验说明子类方法可省略参数类型,其目的肯定不是为了方便重构。那真正目的是什么呢?

在 PHP 7.1 里有一个新功能,是『可设置方法或函数的参数和返回类型是否可以为 null』。其中有一条看上去比较别扭的规则:『子类方法参数类型范围放宽(即父类参数若不能为 null ,子类参数可支持 null),但返回类型缩紧(父类若不能返回 null,子类必须也不行;若父类可以返回 null,子类可以不返回 null)』,当时我很简单说了一句,是因为 『Liskov 替换原则』,但没有做深入介绍。身边的 PHPer 们关注 OOP 原则的不多,但我认为它应该被每个工程师知道,还是介绍一下。

Liskov 替换原则简单一句话:父类出现的地方,替换成子类也能运行,即子类可无脑替换父类。

举个例子,人可以喝酒,喝茶,喝可乐,喝各种饮料,但人作为哺乳动物,怎么着都能喝水吧?但反过来,哺乳动物能喝水,但不一定能喝酒喝茶喝可乐,所以人是哺乳动物的子类。

从语言设计的角度来说,子类就应该是父类的加强版,就是要能比父类处理更多的对象类型,而被覆写的方法参数类型的扩大,也是这一原则的体现。

再来说可能有点绕的返回类型,为什么子类要缩小返回的范围呢?其实只要假设一个方法的返回会作为另外一个方法的参数,就很好想了。比如一个『水果饮料厂』类,有一个『生产』方法,返回『水果汁』,并传给了『小朋友』的『喝』方法。有一个『橘子汁工厂』类属于『水果饮料厂』的子类,它的『生产』方法返回类型缩紧,只能返回『橘子汁』,依然给『小朋友』『喝』,并不会出现任何问题。

再举一个反例。如果又出现一个『水果饮料厂』的子类,其『生产』方法除了返回水果汁,还能返回果酿酒,那这个子类很显然不能冒着给小朋友喝酒的风险去替换父类。

说完了 Liskov 替换原则,我们再来看看 7.2 里的这个改进,我们这时应该知道其实这也是 Liskov 原则的体现。目前来说,替换原则在 PHP 的实现并不完全。可能有人觉得这个版本是不是也支持『父类没有返回类型,子类可以有返回类型』呢?遗憾的是至少在 7.2 这个版本,并不支持,大家可以自行实验一下。

7.2 的另外一个新功能,是 object 可以作为任何对象的类型。见官方提供例子:

<?phpfunction test(object $obj) : object{    return new SplQueue();}test(new StdClass());

其实在 7.2 发布之前,也是出于替换原则,有过一次关于『是否子类可以用 object 类型来替代被覆盖的方法对象参数的类型』,但最终投票并没有通过。虽然我不知道原因,但起码有人提了。

另外目前 PHP 不能像 Java 那样重载(overload),没有办法可以指定覆盖的方法的类型(目前只能把类型直接去掉,有点太粗暴):

<?phpclass Foo{}class FooFoo extends Foo{}class Bar{    public function foo(FooFoo $foo)    {    }}class BarBar extends Bar{    public function foo(Foo $foo) // 依然会报『子类不兼容父类方法格式』的错误    {    }}

但 PHP 也在不断的变化不是吗?最近 PHP 版本迭代这么快,我对 PHP 成为一个支持更多 OOP 特性的语言还是非常有信心的!


分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 分析PHP7.2忽略父类方法以及Liskov替换原则相关问题

相关文章

  • 2022-04-29那些你不知道的Photoshop冷知识技巧
  • 2022-04-29Thinkphp极验滑动验证码实现步骤解析
  • 2022-04-29Web移动端Fixed布局的解决方案
  • 2022-04-29CSS实现瀑布流的两种方式
  • 2022-04-29array_values()在php中返回数组的操作实例
  • 2022-04-29Bootstrap中switch的用法是什么
  • 2022-04-29PhotoShop打造可爱的糖果文字特效制作教程
  • 2022-04-29由JS实现的织梦cms版3D球面标签云 效果与flash版的
  • 2022-04-29替换uploadify用Huploadify实现上传图片或文件
  • 2022-04-29Photoshop多边形套索工具无法闭合BUG(单击,双击,Esc,回车)均无效的解决办法

文章分类

  • dedecms
  • ecshop
  • z-blog
  • UcHome
  • UCenter
  • drupal
  • WordPress
  • 帝国cms
  • phpcms
  • 动易cms
  • phpwind
  • discuz
  • 科汛cms
  • 风讯cms
  • 建站教程
  • 运营技巧

最近更新的内容

    • Discuz怎么修改admin.php
    • php如何生成随机字符串并不重复
    • Centos7 yum安装php的方法
    • nginx报错502怎么办?解决方案分享
    • 解决JavaScript中数组排序sort不发生改变
    • 搜索引擎优化中关键词的分类
    • 织梦DEDECMS首页调用单页文档内容并带过滤HTML的方
    • CorelDraw制作金色质感小球教程
    • mysql聚簇索引和非聚簇索引的区别
    • Photoshop制作61儿童节绚丽艺术字教程

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有