怎么理解PHP7.2忽略父类方法以及Liskov替换原则相关问题

技术怎么理解PHP7.2忽略父类方法以及Liskov替换原则相关问题这篇文章主要介绍“怎么理解PHP7.2忽略父类方法以及Liskov替换原则相关问题”,在日常操作中,相信很多人在怎么理解PHP7.2忽略父类方法以及Li

本文主要介绍“如何理解PHP7.2的父方法以及Liskov替换原理的相关问题”。在日常操作中,相信很多人对于如何理解PHP7.2的父方法以及Liskov替换原理的相关问题都有疑问。边肖查阅了各种资料,整理出简单易用的操作方法,希望能帮助大家解答“如何理解PHP7.2的母法以及Liskov替换原理的相关问题”的疑惑!接下来,请和边肖一起学习!

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

PHP 7.2已经问世一段时间了。只要你关心PHP的发展,你应该已经阅读了所有关于新版本的新改进。这只是一个可能被误解的新功能。

当子类覆盖父方法时,PHP 7.2可以忽略父方法的已定义参数的类型提示:

classFoo

{

public functionbar(someCLaSS $ obj){ }

}

classFoobarextendsFoo

{

Publicfunctionbar($obj){}//这是PHP7.2之前的错误。

}在看一些介绍这个功能的网站时,我说它的目的是“方便重新配置”。如果将来父方法的参数类型改变了,子类就不必再全部改变了”。听起来很合理。根据这种说法,它意味着如果子类忽略了父方法的参数类型,那么当调用它时,它仍然会检查参数类型。实际情况是否是这样,通过做一个实验就知道了:

?服务器端编程语言(Professional Hypertext Preprocessor的缩写)

classFoo

{

}

分类栏

{

publicfunctionsetFoo(Foo$foo)

{

}

}

classBarKidextendsBar

{

publicfunctionsetFoo($foo)

{

}

}

$ kid=newBarKid

$ kid-SetFoo(' Iamstring!');如果上面的语句是正确的,那么在接受字符串参数时,setFoo应该会报告一个错误。但是,上面的代码在7.2下没有任何错误信息,但是如果将参数类型添加到子类的setFoo方法中,它会立即报告错误。记得网上很多说法都不可信,除了我的小站.

上述实验表明子类方法可以省略参数类型,其目的当然不是为了方便重构。真正的目的是什么?

PHP 7.1中新增了一个函数,就是「可以设置方法或函数的参数和返回类型是否可以为空」。有一个规则看起来比较尴尬:“子类方法参数类型的范围比较宽松(即如果父类参数不能为null,子类参数可以支持null),但是返回类型比较紧(如果父类不能返回null,子类一定不能;如果父类可以返回null,子类就不能返回null)”,当时我只是简单的说了一句“娴Liskov替换原则”,但我没有深入介绍。我身边的PHPer不太关注OOP原理,但我觉得应该是每个工程师都知道的,下面就来介绍一下。

Liskov的替换原理很简单:在父类出现的地方,用子类替换也可以运行,即子类可以不假思索地替换父类。其实从语言设计的角度来说,我觉得这个原则是对自然规律的模仿。它不是简单的“模仿”。有兴趣的话可以看看新博客《企鹅不是鸟》。

比如人可以喝酒,可以喝茶,可以喝可乐,可以喝各种饮料,但是作为哺乳动物,人到底能不能喝水呢?另一方面,哺乳动物会喝水,但不一定会喝茶喝可乐,所以人是哺乳动物的一个子类。

从语言设计的角度来看,子类应该是父类的增强版,也就是应该能够处理比父类更多的对象类型,被覆盖的方法参数类型的扩展也体现了这个原则。

让我们谈谈返回类型,它可能有点迂回。子类为什么要缩小返回范围?事实上,很容易想到假设一个方法的返回将被用作另一个方法的参数。比如“水果饮料厂”这一类,有一种“生产”方式,就是把“果汁”退回来,传给“孩子”去“喝”。有一家橙汁厂,属于水果饮料厂的子类。其“制作”方法的返回式比较紧,只能返回“橙汁”,仍然给“孩子”喝,没有任何问题。

再举一个反例。如果有“水果饮料厂”的另一个子类,它的“生产”方法可以返回果酒和果汁,那么这个

子类很显然不能冒着给小朋友喝酒的风险去替换父类。

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

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

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

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

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

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

到此,关于“怎么理解PHP7.2忽略父类方法以及Liskov替换原则相关问题”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/96650.html

(0)

相关推荐

  • Kafka为什么那么快

    技术Kafka为什么那么快这篇文章主要介绍“Kafka为什么那么快”,在日常操作中,相信很多人在Kafka为什么那么快问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Kafka为什么那么快”

    攻略 2021年11月13日
  • dbms_xplan.display_cursor包与高级所有统计上次查看绑定区别是什么

    技术dbms_xplan.display_cursor包与ADVANCED ALLSTATS LAST PEEKED_BINDS区别是什么dbms_xplan.display_cursor包与ADVANCED ALLST

    攻略 2021年12月24日
  • MySQL中的InnoDB索引优化方法是什么

    技术MySQL中的InnoDB索引优化方法是什么这篇文章主要介绍“MySQL中的InnoDB索引优化方法是什么”,在日常操作中,相信很多人在MySQL中的InnoDB索引优化方法是什么问题上存在疑惑,小编查阅了各式资料,

    攻略 2021年12月4日
  • C/C++值传递和址传递有什么区别

    技术C/C++值传递和址传递有什么区别这篇文章主要为大家展示了“C/C++值传递和址传递有什么区别”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C/C++值传递和址传递有什么

    攻略 2021年10月27日
  • 如何利用Winrm.vbs绕过白名单限制执行任意代码

    技术如何利用Winrm.vbs绕过白名单限制执行任意代码这篇文章主要为大家展示了“如何利用Winrm.vbs绕过白名单限制执行任意代码”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习

    攻略 2021年11月1日
  • MySQL FLTWL的堵塞和被堵塞分析

    技术MySQL FLTWL的堵塞和被堵塞分析这篇文章主要介绍“MySQL FLTWL的堵塞和被堵塞分析”,在日常操作中,相信很多人在MySQL FLTWL的堵塞和被堵塞分析问题上存在疑惑,小编查阅了各式资料,整理出

    攻略 2021年11月10日