在PHP 7.4中加入了類型屬性,並對PHP的類型系統進行了重大改進。這些變更是完全可選的,並且不會破壞先前的版本。
在這篇文章中,我們將深入了解這個特性,但首先讓我們總結最重要的幾點:
● 它們自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;
var_dump($foo->bar); Fatal error: Uncaught Error: Typed property Foo::$bar must not be accessed before initialization
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]; }
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)();
##● 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)的詳細內容。更多資訊請關注PHP中文網其他相關文章!