Typattribute wurden in PHP 7.4 hinzugefügt und es wurden wesentliche Verbesserungen am PHP-Typsystem vorgenommen. Diese Änderungen sind völlig optional und beeinträchtigen frühere Versionen nicht.
In diesem Artikel werfen wir einen tieferen Blick auf diese Funktion, aber fassen wir zunächst die wichtigsten Punkte zusammen:
● Sie sind seit PHP 7.4 verfügbar
● Das sind sie nur innerhalb von Klassen verfügbar und erfordern Zugriffsmodifikatoren: public, protected oder private; oder var.
● Alle Typen außer void und callable
them Was tatsächlich passiert, ist Folgendes:
class Foo { public int $a; public ?string $b = 'foo'; private Foo $prop; protected static string $static = 'default'; }
# uninitialized
Bevor wir uns die interessanten Dinge ansehen, wollen wir zunächst einen wichtigen Aspekt der Typeigenschaften besprechen.
Ungeachtet dessen, was Sie auf den ersten Blick sehen, ist der folgende Code gültig:
class Foo { public int $bar; } $foo = new Foo;
Auch wenn der Wert von $bar keine Ganzzahl ist, wirft PHP nach dem Erstellen eines Objekts Foo einfach „When“ aus Es tritt ein Fehler auf, auf $bar wird zugegriffen:
var_dump($foo->bar); Fatal error: Uncaught Error: Typed property Foo::$bar must not be accessed before initialization
Wie Sie der Fehlermeldung entnehmen können, gibt es einen neuen „Variablenstatus“: nicht initialisiert.
Wenn $bar keinen Typ hat, ist sein Wert null. Da Typen jedoch null sein können, gibt es keine Möglichkeit festzustellen, ob eine Eigenschaft vom Typ null festgelegt oder einfach vergessen wurde. Deshalb wurde „uninitialized“ hinzugefügt.
Vier Dinge, die Sie bei der Nichtinitialisierung beachten sollten:
● Eine nicht initialisierte Eigenschaft kann nicht gelesen werden, und dies führt zu einem schwerwiegenden Fehler.
● Da beim Zugriff auf Eigenschaften der nicht initialisierte Status überprüft wird, ist es möglich, Objekte mit nicht initialisierten Eigenschaften zu erstellen, auch wenn ihr Typ nicht nullbar ist.
● Sie können zuerst in eine nicht initialisierte Eigenschaft schreiben und sie dann lesen.
● Wenn Sie „unset“ für eine typisierte Eigenschaft verwenden, wird diese nicht initialisiert, während das Aufheben einer nicht typisierten Eigenschaft sie auf null setzt.
Beachten Sie insbesondere, dass der folgende Code gültig ist, wenn nach der Erstellung des Objekts eine nicht initialisierte, nicht nullbare Eigenschaft festgelegt wird
class Foo { public int $a; } $foo = new Foo; $foo->a = 1;
Obwohl er nur beim Lesen des Eigenschaftswerts Initialize überprüft wird Zustand, aber führen Sie beim Schreiben von Eigenschaftswerten eine Typvalidierung durch. Dadurch können Sie sicherstellen, dass ungültige Typen nicht als Eigenschaftswert enden.
#Standardwerte und Konstruktoren
Sehen wir uns genauer an, wie man einen typisierten Wert initialisiert. Für Skalartypen kann ein Standardwert bereitgestellt werden:
class Foo { public int $bar = 4; public ?string $baz = null; public array $list = [1, 2, 3]; }
Beachten Sie, dass Sie null nur als Standardwert verwenden können, wenn der Typ tatsächlich leer ist. Das mag offensichtlich erscheinen, aber es gibt ein altes Verhalten bei Parameterstandards, das Folgendes zuließ:
function passNull(int $i = null) { /* … */ } passNull(null);
Glücklicherweise erlauben Typattribute dieses verwirrende Verhalten nicht.
Beachten Sie außerdem, dass Objekt- oder Klassentypen keine Standardwerte haben können. Sie sollten Konstruktoren verwenden, um ihre Standardwerte festzulegen.
Der offensichtliche Ort zum Initialisieren eines typisierten Werts ist natürlich der Konstruktor:
class Foo{ private int $a; public function __construct(int $a) { $this->a = $a; } }
Aber denken Sie auch daran, was ich zuvor erwähnt habe: Das Schreiben nicht initialisierter Eigenschaften außerhalb des Konstruktors ist gültig. Solange nichts von der Eigenschaft gelesen wird, wird die nicht initialisierte Prüfung nicht durchgeführt.
# Typen von Typen
Was genau kann also typisiert werden und wie? Ich habe bereits erwähnt, dass typisierte Eigenschaften (vorerst) nur in Klassen gültig sind, sie benötigen An Der Zugriffsmodifikator oder das Schlüsselwort var geht ihnen voran.
Für die verfügbaren Typen können fast alle Typen außer void und callable verwendet werden.
Da „void“ keinen Wert bedeutet, ist es sinnvoll, dass es nicht für eingegebene Werte verwendet werden kann. Callable ist etwas anders.
Wie Sie sehen können, kann „aufrufbar“ in PHP so geschrieben werden:
Aber denken Sie auch daran, was ich zuvor erwähnt habe: Das Schreiben nicht initialisierter Eigenschaften außerhalb des Konstruktors ist gültig. Solange nichts von der Eigenschaft gelesen wird, wird die nicht initialisierte Prüfung nicht durchgeführt.
Sehen Sie, ein „Callable“ in PHP kann so geschrieben werden:
$callable = [$this, 'method'];
Angenommen, Sie haben den folgenden (ungültigen) Code:
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)();
In diesem Fall $callable verweist auf die private Bar::Methode, wird aber im Kontext von Foo aufgerufen. Aufgrund dieses Problems wurde beschlossen, keinen aufrufbaren Support hinzuzufügen.
Das ist jedoch keine große Sache, da „Closure“ ein gültiger Typ ist und sich den $this-Kontext merkt, in dem er erstellt wurde.
Hier ist übrigens die Liste aller verfügbaren Typen:
● bool
● int
● float
● string
● Array
● iterierbar
● Objekt
● ? (nullable)
● self & parent
● Klassen und Schnittstellen
# Erzwungene und strikte Typisierung
PHP ist eine dynamische Sprache, die wir lieben und hassen. Wann immer möglich, wird sie Typen umwandeln. Angenommen, Sie übergeben eine Zeichenfolge, bei der eine Ganzzahl erwartet wird, versucht PHP, die Zeichenfolge automatisch zu konvertieren:
function coerce(int $i) { /* … */ } coerce('1'); // 1
Das gleiche Prinzip gilt für Typattribute.
Der folgende Code ist gültig und wandelt „1“ in 1 um.
class Bar { public int $i; } $bar = new Bar; $bar->i = '1'; // 1
Wenn Ihnen dieses Verhalten nicht gefällt, können Sie es deaktivieren, indem Sie eine strikte Typisierung deklarieren:
declare(strict_types=1); $bar = new Bar; $bar->i = '1'; // 1 Fatal error: Uncaught TypeError: Typed property Bar::$i must be int, string used
#Type Differences and Inheritance
Even Mit PHP 7.4 wurden verbesserte Typunterschiede eingeführt, die Typeigenschaften bleiben jedoch unverändert.
Das bedeutet, dass Folgendes nicht gültig ist:
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)
Wenn Ihnen das obige Beispiel nicht wichtig erscheint, sollten Sie sich Folgendes ansehen:
class Foo { public self $prop; } class Bar extends Foo { public self $prop; }
Bevor Sie den Code ausführen, PHP ersetzt hinter den Kulissen self durch die konkrete Klasse, auf die es verweist.
这意味着在本例中会抛出相同的错误。处理它的唯一方法,是执行以下操作:
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
Das obige ist der detaillierte Inhalt vonTypisierte Eigenschaften in PHP 7.4. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!