您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > php

PHP 7.4类型属性实例详解

时间:2019-08-07 15:39:52  来源:  作者:

根据php RFC日程,PHP 7.4预期将会在今年11月份,当然接下来PHP 8被也已经上了历程。7.4将至,PHP 8可期!那么即将到来PHP 7.4有啥新特性和功能呢?本文以虫虫以类型方面的增强来予以介绍,和大家一起学习。

PHP 7.4类型属性实例详解

 

概述

PHP 7.4为了增强类型新增加了类型化的类属性,并对PHP的类型系统进行了重大改进。当然这些变化都是可选功能,是完全向前对老版本兼容,不会破坏以前的老代码。新的类型特性:

从PHP 7.4开始支持。

仅在类中可用,并且需要访问修饰符:public,protected或private或var。

允许使用除了void和callable以外的所有类型。

其表现如下例:

PHP 7.4类型属性实例详解

 

Uninitialized

在上面的例子中,首先映入我们眼帘的是:

class Foo
{
public int $bar;
}
$foo = new Foo;

即使创建Foo对象后$bar的值不是整数,PHP只会在访问$bar时抛出错误:

var_dump($foo->a);

Fatal error: Uncaught Error: Typed property Foo::$bar

must not be accessed before initialization

从错误消息可以得出,有一种新的"可变状态":uninitialized。

如果$bar没有类型,则其值将为null。类型可以是空值,无法确定是否设置了类型化的可空属性,或者忘记设置了。所以新添加了"uninitialized"这个新类型加以区别。

关于uninitialized,主要注意:

无法访问未初始化的属性,如果坚持要访问会抛出致命错误。

在访问属性时会检查未初始化状态,所以即使其类型不可为空,也可以创建具有未初始化属性的对象。

可以在读取之前写入未初始化的属性。

对类型化属性使用unset将使其未初始化,取消设置无类型属性将使设置为null。

下面例子中在构造对象后设置未初始化的,不可为空的属性,是有效的:

class Foo
{
public int $a;
}
$foo = new Foo;
$foo->a = 1;

虽然只是读取属性值时检查未初始化状态,但在写入时会进行类型验证。所以可以确保不会被赋予错误类型的属性值。

默认值和构造函数

再来看看如何初始化类型值。在标量类型的情况下,可以提供默认值:

class Foo
{
 public int $bar = 4;
 public ?string $baz = null;
 public array $list = [1, 2, 3];
}

注意,如果类型实际上可以为空,则只能使用null作为默认值。可能看起来很明显,但是参数默认值存在一些遗留行为,其中允许以下内容:

function passNull(int $i = null)
{ /* … */ }
passNull(null);

好消息是,类型属性不允许这种令人困惑的行为。

另请注意对对象或类类型的默认值是不可设置的。应该使用构造函数来设置其默认值。

初始化类型值的显而易见的地方当然是构造函数:

class Foo
{
 private int $a;
 public function __construct(int $a)
 {
 $this->a = $a;
 }
}

在构造函数之外写入未初始化的属性是有效的。只要不去访问这些属性,就不会执行未初始化的检查。

支持的类型

上面我们说了类型属性只能在类中使用,并且需要访问修饰符或前面的var关键字。从可用类型来看,除了void和callable之外,几乎所有类型都可以使用。void类型表示没有值,它不能用于键入值。然而,callable类型则更复杂点。

PHP中的"callable"类型用法是:

$callable = [$this, 'method'];

假设你代码如下:

PHP 7.4类型属性实例详解

 

在上面的示例中,$callable引用私有的Bar::method方法,但是调用是在Foo的上下文中调用。由于作用域不同,所以callable也不能在类型属性中使用。

这没什么大不了的,因为Closure是一个有效的类型,它将记住构造它的$ this上下文。

除此之外,所有可用类型的列表如下:

布尔型(bool),整型(int),浮点型(float),字符串(string),数组(array),iterable,对象,?(nullable),self 和parent,类和接口

强制和严格的类型

PHP具有动态语言具有的类型灵活性,它会尽可能地强制或转换类型。假设传递给整型变量一个字符串,PHP将尝试自动转换该字符串:

function coerce(int $i)
{ … }
coerce('1'); 
// 1

类型属性也使用同样的原则。以下代码有效,会自动将'1'转换为1。

class Bar
{
 public int $i;
}
$bar = new Bar;
$bar->i = '1'; 
// 1

如果不喜欢这种行为,可以通过声明为严格类型检查来禁用:

declare(strict_types=1);
$bar = new Bar;
$bar->i = '1'; 

上述语句以错误类型赋值时候,在严格类型检查(strict_types=1)下会抛出严重错误:

Fatal error: Uncaught TypeError:

Typed property Bar::$i must be int, string used

类型变量和继承

尽管PHP 7.4引入了改进的类型变量,但类型属性仍然是不变的。这意味着以下内容无效:

class A {}
class B extends A {}
class Foo
{
 public A $prop;
}
class Bar extends Foo
{
 public B $prop;
}

Fatal error: Type of Bar::$prop must be A (as in class Foo)

如果上面的看起起不明显,再举个例子:

class Foo
{
 public self $prop;
}
class Bar extends Foo
{
 public self $prop;
}

在运行代码之前,PHP将使用它引用的具体类后台替换self。所以上面的代码也会抛出相同的错误。处理它的唯一正确姿势是:

class Foo
{
 public Foo $prop;
}
class Bar extends Foo
{
 public Foo $prop;
}

说到继承,可能会发现很难找到任何好的用例来覆盖继承属性的类型。

值得注意的是,可以更改继承属性的类型,但前提是访问修饰符也从私有更改为protected或public。下面代码是正确的:

class Foo
{
 private int $prop;
}
class Bar extends Foo
{
 public string $prop;
}

不允许将类型从可空变为非可空,反之亦然。

class Foo
{
 public int $a;
 public ?int $b;
}
class Bar extends Foo
{
 public ?int $a;
 public int $b;
}

Fatal error: Type of Bar::$a must be int (as in class Foo)

总结

本文我们以类型化属性是PHP为例介绍了PHP 7.4带来的新的变化和加强,更多的功能,可以参考PHP RFC。对于即将到来的7.4版本和后面可期的PHP 8 ,我们只有以活到老,学到老的态度才能跟上新技术的步伐。"求求你别更新了,我快跟不上啦!"绝非一个IT人应该有的态度!



Tags:PHP 7.4   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
根据PHP RFC日程,PHP 7.4预期将会在今年11月份,当然接下来PHP 8被也已经上了历程。7.4将至,PHP 8可期!那么即将到来PHP 7.4有啥新特性和功能呢?本文以虫虫以类型方面的增强来予以...【详细内容】
2019-08-07  Tags: PHP 7.4  点击:(254)  评论:(0)  加入收藏
短闭包 RFC短闭包实现更简洁的单行书写。array_map(function (User $user) {return $user->id;}, $users)array_map(fn(User $user) => $user->id, $users)关于短闭包的一些...【详细内容】
2019-06-26  Tags: PHP 7.4  点击:(541)  评论:(0)  加入收藏
▌简易百科推荐
序言:前段时间织梦因为版权的问题在网上闹得沸沸扬扬,也提醒了众多开发者选择cms上应该谨慎使用,今天给大家展示一款自己搭建的内容管理系统,不用担心版权的问题,而且非常容易维...【详细内容】
2021-11-30  小程序软件开发    Tags:管理系统   点击:(34)  评论:(0)  加入收藏
准备安装包(PHP: Hypertext Preprocessor)下载安装包以及组件wget https://www.php.net/distributions/php-8.0.0.tar.bz2wget https://github.com/phpredis/phpredis/archive...【详细内容】
2021-11-09  mimic96    Tags:PHP   点击:(40)  评论:(0)  加入收藏
golang context 很好用,就使用php实现了github地址 : https://github.com/qq1060656096/php-go-context context使用闭坑指南1. 将一个Context参数作为第一个参数传递给传入和...【详细内容】
2021-11-05  1060656096    Tags:PHP   点击:(41)  评论:(0)  加入收藏
一段数组为例:$list = array:4 [ 0 => array:7 [ "id" => 56 "mer_id" => 7 "order_id" => "wx163265961408769974" "is_postage" => 0 "store_name" => "奇...【详细内容】
2021-09-29  七七小影视    Tags:PHP   点击:(65)  评论:(0)  加入收藏
利用JS的CryptoJS 3.x和PHP的openssl_encrypt,openssl_decrypt实现AES对称加密解密,由于需要两种语言对同一字符串的操作,而CryptoJS 的默认加密方式为“aes-256-cbc”,PHP端也...【详细内容】
2021-09-16  李老师tome    Tags:对称加密   点击:(79)  评论:(0)  加入收藏
1、checkdate()验证格利高里日期即:日期是否存在。checkdate(month,day,year);month必需。一个从 1 到 12 的数字,规定月。day必需。一个从 1 到 31 的数字,规定日。year必需。...【详细内容】
2021-08-31  七七小影视    Tags:时间函数   点击:(80)  评论:(0)  加入收藏
对于各类开发语言来说,整数都有一个最大的位数,如果超过位数就无法显示或者操作了。其实,这也是一种精度越界之后产生的精度丢失问题。在我们的 PHP 代码中,最大的整数非常大,我...【详细内容】
2021-08-26  硬核项目经理    Tags:PHP   点击:(83)  评论:(0)  加入收藏
遵从所有教材以及各类数据结构相关的书书籍,我们先从线性表开始入门。今天这篇文章更偏概念,是关于有线性表的一个知识点的汇总。上文说过,物理结构是用于确定数据以何种方式存...【详细内容】
2021-07-19  硬核项目经理    Tags:线性表   点击:(94)  评论:(0)  加入收藏
一、开启IIS全部功能。二、部署PHP1.官网下载并解压PHP: https://windows.php.net/downloads/releases/2.将php.ini-development文件改为php.ini3.修改php.ini(1)去掉注释,并修...【详细内容】
2021-07-15  炘蓝火诗  今日头条  Tags:PHP环境   点击:(129)  评论:(0)  加入收藏
一、环境说明本文中使用本地VM虚机部署测试。OS:CentOS Linux release 7.8.2003 (Core)虚机配置:2核CPU、4G内存①系统为CentOS 7.8 x64最小化安装,部署前已完成系统初始化、...【详细内容】
2021-06-25  IT运维笔记  今日头条  Tags:PHP8.0.7   点击:(141)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条