PHP7.1新功能之Nullable Type用法分析


Posted in PHP onSeptember 26, 2016

本文实例分析了PHP7.1新功能之Nullable Type用法。分享给大家供大家参考,具体如下:

在 PHP5 时代,PHP 的参数已经支持 type hint(除了基本类型),想必大家应该很熟悉;后来 PHP7 时代来临,PHP 也可以指定返回值的类型(以及基本类型的 type hint)。但我们可能还有一种需求:除了指定的 type hint,参数或者返回值也能定义可以为 null,举个例子,假如我们有一个 UserRepository 类,有一个方法叫 find($id),此方法可返回一个 User 对象,也可返回 null,在 PHP7.1 里就可以这么定义了:
...

class UserRepository
{
  ...
  public function find($id): ?User
  {
    ...
    return $user;
    // or
    // return null;
  }
}

但这么申明以后,如果返回 null,是否必须显式调用 return null,这就得等 7.1 正式出来之后再验证了。

当然还有参数设定是否 nullable 的例子,直接复制官网里的例子:

function say(?string $msg) {
  if ($msg) {
    echo $msg;
  }
}
say('hello'); // ok -- prints hello
say(null); // ok -- does not print
say(); // error -- 丢失属性
say(new stdclass); //error -- 类型错误

以上便是 nullable type 的大致用法,但其实引入了此种机制以后,有很多细节都是需要注意的,比如在继承的时候,子类允许去掉父类同名方法的返回类型为 nullable 的设置:

interface Fooable
{
  public function foo(): ?Fooable;
}
interface StrictFooable extends Fooable
{
  public function foo(): Fooable; // valid
}

但反过来,子类是不允许添加返回类型可以为 nullable 的。

然后我们再来看看参数类型的情况。跟返回类型相反,子类在复写父类方法时,参数类型是可以在父类参数的基础上添加 nullable 属性的:

interface Fooable
{
  public function foo(Fooable $f);
}
interface LooseFoo extends Fooable
{
  function foo(?Fooable $f);
}

反过来不行。可能刚看到这点,大家都会有疑问为什么返回类型和参数类型会有这样的设定。其实大家想想 Liskov 替换原则就明白了。
最后是关于参数默认值的问题,目前 PHP 是可以这样做的:

function foo_default(Bar $bar = null) {}
foo_default(new Bar); // valid
foo_default(null); // valid
foo_default(); // valid

但如果改成 nullable 的类型申明,即使传入的参数是 null,也不能在调用的时候省略不写:

function foo_nullable(?Bar $bar) {}
foo_nullable(new Bar); // valid
foo_nullable(null); // valid
foo_nullable(); // INVALID!

由此可见 nullable 类型的目的是为了允许某个参数带类型而且可以为 null,而默认值为 null 的参数就真的是想告诉大家某个参数的默认值是 null。以前我们如果允许某些 setter 可以置空,写的代码总是觉得怪怪的:

public function setIssueAt(\DateTime $issueAt = null)

觉得怪最大的原因我想是因为这样的一个 setter 居然可以不传参数!

这下好了,有了 nullable type,我们也就不会写那么别扭的代码了。

当然,nullable type 和 = null 是可以同时用的。这里就不写例子了,效果跟只用 = null 没有区别。

最后,还是继承:如果父类方法参数是 nullable 的,那么子类可以使用 = null

interface Contract
{
  public function method(?Foo $foo): bool;
}
class Implementation implements Contract
{
  public function method(?Foo $foo = null): bool
  {
    return is_null($foo);
  }
}

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
paypal即时到账php实现代码
Nov 28 PHP
解析将多维数组转换为支持curl提交的一维数组格式
Jul 08 PHP
php操作mysql数据库的基本类代码
Feb 25 PHP
通过Email发送PHP错误的方法
Jul 20 PHP
Zend Framework分页类用法详解
Mar 22 PHP
浅谈PHP中的数据传输CURL
Sep 06 PHP
PHP快速排序quicksort实例详解
Sep 28 PHP
PHP实现图片的等比缩放和Logo水印功能示例
May 04 PHP
PHP实现找出链表中环的入口节点
Jan 16 PHP
PHP __call()方法实现委托示例
May 20 PHP
php字符串函数 str类常见用法示例
May 15 PHP
如何理解PHP核心特性命名空间
May 28 PHP
php实现在新浪云中使用imagick生成缩略图并上传的方法
Sep 26 #PHP
php版交通银行网银支付接口开发入门教程
Sep 26 #PHP
php版微信公众平台实现预约提交后发送email的方法
Sep 26 #PHP
php版微信公众平台入门教程之开发者认证的方法
Sep 26 #PHP
php is_executable判断给定文件名是否可执行实例
Sep 26 #PHP
PHP弱类型的安全问题详细总结
Sep 25 #PHP
php中mkdir()函数的权限问题分析
Sep 24 #PHP
You might like
Php Image Resize图片大小调整的函数代码
2011/01/17 PHP
Yii框架通过请求组件处理get,post请求的方法分析
2019/09/03 PHP
Javascript - HTML的request类
2007/01/09 Javascript
事件冒泡是什么如何用jquery阻止事件冒泡
2013/03/20 Javascript
对js关键字命名的疑问介绍
2014/04/25 Javascript
javascript原始值和对象引用实例分析
2015/04/25 Javascript
jquery合并表格中相同文本的相邻单元格
2015/07/17 Javascript
详解JavaScript中数组的相关知识
2015/07/29 Javascript
浅谈toLowerCase和toLocaleLowerCase的区别
2016/08/15 Javascript
js+div+css下拉导航菜单完整代码分享
2016/12/28 Javascript
jQuery使用DataTable实现删除数据后重新加载功能
2017/02/27 Javascript
详解angularJs中关于ng-class的三种使用方式说明
2017/06/02 Javascript
微信小程序实现提交input信息到后台的方法示例
2019/01/19 Javascript
vue cli4下环境变量和模式示例详解
2020/04/09 Javascript
JS实现鼠标按下拖拽效果
2020/07/23 Javascript
[30:51]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#1Liquid VS MVP.Phx第一局
2016/03/04 DOTA
python正常时间和unix时间戳相互转换的方法
2015/04/23 Python
python3 selenium 切换窗口的几种方法小结
2018/05/21 Python
对Python 3.5拼接列表的新语法详解
2018/11/08 Python
python实现逐个读取txt字符并修改
2018/12/24 Python
Python3.5文件读与写操作经典实例详解
2019/05/01 Python
python使用pandas处理大数据节省内存技巧(推荐)
2019/05/05 Python
Pytorch模型转onnx模型实例
2020/01/15 Python
Python %r和%s区别代码实例解析
2020/04/03 Python
Python telnet登陆功能实现代码
2020/04/16 Python
Python爬虫之Selenium警告框(弹窗)处理
2020/12/04 Python
用python对oracle进行简单性能测试
2020/12/05 Python
HTML5 device access 设备访问详解
2018/05/24 HTML / CSS
馥绿德雅美国官方网站:Rene Furterer头皮护理专家
2019/05/01 全球购物
介绍一下代理模式(Proxy)
2014/10/17 面试题
PyQt 如何创建自定义QWidget
2021/03/24 Python
出纳的岗位职责
2013/11/09 职场文书
工作态度怎么写
2015/06/25 职场文书
优质服务心得体会(共4篇)
2016/01/22 职场文书
医生行业员工的辞职信
2019/06/24 职场文书
MySql重置root密码 --skip-grant-tables
2022/04/11 MySQL