正在这篇文章中,咱们将深化理解这个特点,但起首让咱们总结最首要的几点:
● 它们自PHP 7.4起可用
● 它们只正在类中可用,而且需求拜访润饰符:public、protected或private;或var.
● 除了了void以及callable以外,一切类型都是容许的
他们的实际状况是这样的:
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; } }
但也请记住我后面提到的:正在结构函数内部写入未初始化的属性是无效的。只需不隶属性中读取任何内容,就没有会执行未初始化反省。
#类型的类型
那末终究甚么能够输出,若何输出呢?我曾经提到类型化属性只正在类中无效(今朝),它们需求一个拜访润饰符或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 7.4中的类型属性(Typed Properties)的具体内容,更多请存眷资源魔其它相干文章!
标签: php7开发教程 php7开发资料 php7开发自学 Php 7.4
抱歉,评论功能暂时关闭!