PHP 7.4类型属性实例详解

根据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 。
【PHP 7.4类型属性实例详解】class Bar{ public int $i;}$bar = new Bar;$bar->i = '1'; // 1如果不喜欢这种行为,可以通过声明为严格类型检查来禁用:


推荐阅读