0

0

PHP 7.4中的类型属性(Typed Properties)

藏色散人

藏色散人

发布时间:2019-11-30 13:32:11

|

4385人浏览过

|

来源于php中文网

原创

在php 7.4中添加了类型属性,并对php的类型系统进行了重大改进。这些更改是完全可选的,并且不破坏以前的版本。

在这篇文章中,我们将深入了解这个特性,但首先让我们总结最重要的几点:

● 它们自PHP 7.4起可用

● 它们只在类中可用,并且需要访问修饰符:public、protected或private;或var.

● 除了void和callable之外,所有类型都是允许的

立即学习PHP免费学习笔记(深入)”;

他们的实际情况是这样的:

class Foo
{
    public int $a;
    public ?string $b = 'foo';
    private Foo $prop;
    protected static string $static = 'default';
}

#未初始化

在查看有趣的内容之前,首先要讨论类型属性的一个重要方面。

不管你第一眼看到的是什么,下面的代码是有效的:

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

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

var_dump($foo->bar);
Fatal error: Uncaught Error: Typed property Foo::$bar 
must not be accessed before initialization

从错误消息中可以看到,有一种新的“变量状态”:未初始化。

如果$bar没有类型,则其值将为null。但是类型可以为空,因此无法确定是否设置了类型为空的属性,或者只是将其忘记了。这就是为什么添加了“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;
    }
}

但也请记住我前面提到的:在构造函数外部写入未初始化的属性是有效的。只要没有从属性中读取任何内容,就不会执行未初始化检查。

Copy Leaks
Copy Leaks

AI内容检测和分级,帮助创建和保护原创内容

下载

#类型的类型

那么究竟什么可以输入,如何输入呢?我已经提到类型化属性只在类中有效(目前),它们需要一个访问修饰符或var关键字在它们前面。

对于可用类型,除了void和callable之外,几乎所有类型都可以使用。

因为void意味着没有值,所以不能将其用于键入值是有意义的。 callable稍微有点差别。

可见,PHP中的“ callable” 可以这样写:

但也请记住我前面提到的:在构造函数外部写入未初始化的属性是有效的。只要没有从属性中读取任何内容,就不会执行未初始化检查。

看,一个“callable”在PHP可以这样写:

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

假设您有以下(无效)代码:

class Foo
{
    public callable $callable;
    
    public function __construct(callable $callable)
    { /* … */ }
}
class Bar
{
    public Foo $foo;
    
    public function __construct()
    {
        $this->foo = new Foo([$this, 'method'])
    }
    
    private function method()
    { /* … */ }
}
$bar = new Bar;
($bar->foo->callable)();

在本例中,$callable引用私有Bar::方法,但是在Foo的上下文中被调用。由于这个问题,决定不添加callable的支持。

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

顺便说一句,这是所有可用类型的列表:

● bool

● int

● float

● string

● array

● iterable

● object

● ? (nullable)

● self & parent

● Classes & interfaces

#强制类型和严格类型

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'; // 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;
}

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

虽然我同意这种观点,但值得注意的是,可以更改继承属性的类型,但前提是访问修饰符也从private更改为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)
翻译:https://stitcher.io/blog/typed-properties-in-php-74

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

44

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

58

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

11

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

21

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

35

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.7万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 7万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号