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

本文实例分析了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基本语法入门教程》、《PHP运算与运算符用法总结》、《php面向对象程序设计入门教程》、《PHP网络编程技巧总结》、《PHP数组(Array)操作技巧大全》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

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

(0)

相关推荐

  • PHP7 新特性详细介绍

    PHP 的学习新特性 最近做的项目使用了 php7,但感觉有很多新特性没有用起来.就想总结一下,一些可能会用到的新特性.之前使用的环境是 php5.4,所有也会有 php5.5 和 php5.6 的特性总结进来,这里只列出我觉得在项目中可能用到的特性,主要内容来自 php手册的附录. Generators (PHP 5 >= 5.5.0, PHP 7) 通过添加 yield 关键字支持了 generators,Generators 提供了一个更简单的方法实现迭代器,不需要实现 Iterator

  • PHP7标量类型declare用法实例分析

    本文实例讲述了PHP7标量类型declare用法.分享给大家供大家参考,具体如下: php7为了提高执行效率,在函数方法中增加了标量类型(布尔.浮点.整型.字符)的申明特性,节省了对数据类型的检测. php7 仍然支持弱类型检测,即仍然可以使用原来的方式声明形参. 标量声明有两种特性: 强制模式(默认):体现在类型转换上 严格模式 模式声明:declare(strict_types=1); 默认情况值为0,值为1代表为严格校验的模式 可以使用的类型参数: int-float-bool-strin

  • thinkphp在php7环境下提示Cannot use ‘String’ as class name as it is reserved的解决方法

    本文实例讲述了thinkphp在php7环境下提示Cannot use 'String' as class name as it is reserved的解决方法.分享给大家供大家参考,具体如下: 我有一网站之前用php7运行thinkphp没有什么问题,但是最近发现开启验证码的时候发现有错误 Cannot use 'String' as class name as it is reserved 在google baidu搜索了一下还是没有解决方法 于是自己动手解决,看来我是第一个分享出来的人

  • linux平台编译安装PHP7并安装Redis扩展与Swoole扩展实例教程

    本文实例讲述了linux平台编译安装PHP7并安装Redis扩展与Swoole扩展的方法.分享给大家供大家参考,具体如下: 前面<PHP7安装Redis扩展教程[Linux与Windows平台]>一文告诉读者简单的安装Redis的方法,下面我们来实现在linux中编译安装PHP7并安装Redis扩展与Swoole扩展的方法. 编译安装PHP7并安装Redis扩展Swoole扩展: 在编译php7的机器上已经有编译安装过php5.3以上的版本,从而依赖库都有了 本php7是编译成fpm-php

  • centos7 + php7 lamp全套最新版本配置及mongodb和redis教程详解

    所有软件的版本一直会升级,注意自己当时的版本是不是已经更新了. 首先装centos7 如果你忘了设置swap分区,下面的文章可以教你怎么补一个上去: http://www.jb51.net/os/201409/338170.html 装好centos7后默认是不能上网的 cd /etc/sysconfig/network-scripts/ 找到形如ifcfg-enp0s3的文件,修改onboot=yes 然后 service network restart 安装apache2 (centos里叫

  • PHP7新增运算符用法实例分析

    本文实例讲述了PHP7新增运算符用法.分享给大家供大家参考,具体如下: NULL 合并运算符 其实是三元运算符的改造,减少的代码量 //原先的做法 //$lig = isset($_GET['lig'])?$_GET['lig']:'bee'; $lig = $_GET['lig']??'bee'; echo $lig; 运行效果图如下: 太空船运算符(组合比较符) 实质就是大小比较符,不过相比'<'.'>'的返回值多了-1,跟Java的字符串比较compareto()功能类似 <?ph

  • PHP7常量数组用法分析

    本文实例讲述了PHP7常量数组用法.分享给大家供大家参考,具体如下: php7之前define只能是键值对,而php7里可以把数组加进define <?php /** * Created by PhpStorm. * User: bee * Date: 2016/4/23 * Time: 1:27 */ define('NAME',[ 'lig','bee','arr'=>array('ligbee'),array('lig','bee'),'w' ]); echo NAME[0]; echo

  • PHP7.1方括号数组符号多值复制及指定键值赋值用法分析

    本文实例讲述了PHP7.1方括号数组符号多值复制及指定键值赋值用法.分享给大家供大家参考,具体如下: PHPer 们可能都知道 list 的用法,简单来说就是可以在一个表达试里通过数组对多个变量赋值: $values = array('value1', 'value2'); $list($v1, $v2) = $values; 感觉是不是很方便呢?在 PHP 7.1 中,还能更省事儿: [$v1, $v2] = ['foo', 'bar']; 这还不是最给力的,在 PHP 7.1 里我们还可以指

  • yum命令安装php7和相关扩展

    安装php7和相关扩展 rpm -Uvh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm (nginx) rpm -Uvh http://rpms.famillecollet.com/en

  • ecshop适应在PHP7的修改方法解决报错的实现

    ecshop这个系统,到目前也没见怎么推出新版本,如果是新项目,不太建议使用它.不过,因为我一直以来都在使用中,所以不得不更改让其适应PHP新版本.现在PHP 7已经出发行版了,所以更改来继续使用吧.具体的更改有以下方面: (1)将mysql扩展的使用替换掉,改为使用mysqli或pdo: 从php5.5开始,mysql扩展将废弃了. 具体更改的文件在于includes/cls_mysql.php.这是个不小的工程,文件代码太长-- if (!defined('DITAN_ECS')) { di

  • CentOS 7.2.1511 编译安装Nginx1.10.1+MySQL5.7.14+PHP7.0.11

    准备篇 一.防火墙配置 CentOS 7.x默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭firewall: systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service #禁止firewall开机启动 2.安装iptables防火墙 yum install iptables-services #安装 vi /etc/sysconfig/iptables #编辑

  • CentOS 7.2 下编译安装PHP7.0.10+MySQL5.7.14+Nginx1.10.1的方法详解(mini版本)

    一.安装前的准备工作 1.yum update #更新系统 2.yum install gcc gcc-c++ autoconf automake cmake bison m4 libxml2 libxml2-devel libcurl-devel libjpeg-devel libpng-devel libicu-devel #安装php.MySQL.Nngix所依赖的包 3.下载以下包 #我把所有源文件都下载在root目录,读者可自行修改源文件存放目录 3.1 libmcrypt-2.5.8

  • golang 调用 php7详解及实例

    执行php文件 func Test_exec(t *testing.T) { engine.Initialize() ctx := &engine.Context{ Output: os.Stdout, } err := engine.RequestStartup(ctx) if err != nil { fmt.Println(err) } defer engine.RequestShutdown(ctx) err = ctx.Exec("/tmp/index.php") i

  • PHP7匿名类用法分析

    本文实例讲述了PHP7匿名类用法.分享给大家供大家参考,具体如下: 匿名类跟匿名函数一样,创建一次性的简单对象 <?php /** * Created by PhpStorm. * User: bee * Date: 2016/4/24 * Time: 00:17 */ echo '匿名函数'; $anonymous_func = function(){return 'function';}; echo $anonymous_func(); echo '<br>'; echo '<

  • PHP7安装Redis扩展教程【Linux与Windows平台】

    本文实例讲述了PHP7安装Redis扩展的方法.分享给大家供大家参考,具体如下: linux中PHP7安装Redis扩展 1.依次执行 wget -c https://github.com/phpredis/phpredis/archive/php7.zip unzip php7.zip cd phpredis-php7 /YouPath/phpize ./configure --with-php-config=/YouPath/php-config make make install 2.加入

随机推荐