So verwenden Sie schreibgeschützte Eigenschaften in PHP 8.1

0
130

PHP 8.1 fügt Unterstützung für einen schreibgeschützten Modifikator für Klasseneigenschaften hinzu. Eine auf diese Weise gekennzeichnete Eigenschaft kann nur einmal festgelegt werden. Wenn Sie versuchen, den Wert einer schreibgeschützten Eigenschaft nach der Initialisierung zu ändern, wird ein Fehler ausgegeben.

“Schreibgeschützt” ist ein recht vager Begriff mit unterschiedlichen Implikationen in den einzelnen Programmiersprachen. In diesem Zusammenhang ist “schreibgeschützt” bedeutet wirklich “unveränderlich”—Sie können den Wert einer Eigenschaft festlegen, aber er kann später nicht mehr geändert werden.

Schreibgeschützte Eigenschaften schreiben

Fügen Sie den readonly-Modifizierer hinzu, um eine Eigenschaft schreibgeschützt zu machen. Sie sollte zwischen dem Zugriffsmodifizierer der Eigenschaft und ihrem Typhint platziert werden.

class Demo {   öffentliche Zeichenfolge $Mutable;   öffentlicher schreibgeschützter String $Immutable;   öffentliche Funktion __construct( Zeichenfolge $veränderlich, Zeichenfolge $unveränderlich) {   $dies -> Veränderlich = $Veränderlich; $dies -> Unveränderlich = $Unveränderlich; }   }

$Mutable ist eine normale öffentliche Eigenschaft. Sie können seinen Wert jederzeit ändern, entweder innerhalb von Klassenmethoden oder von außerhalb:

$demo = neue Demo("A", "X"); $demo -> änderbar = “B”;

$Immutable ist etwas anders. Sie können seinen Wert immer noch lesen, wann immer Sie möchten, aber alle Änderungen schlagen mit einem Fehler fehl:

//Wirft einen Fehler aus $demo -> Unveränderlich = “Y”; Werbung

Der readonly-Modifizierer wird auch in hochgestuften Konstruktoreigenschaften unterstützt:

class Demo { öffentliche Funktion __construct( public readonly string $Immutable="foobar" ) {} }

Sie können die Eigenschaft in Ihrem Konstruktor weiterhin manuell festlegen, wenn Sie die Werbung mit einem Standardwert verwenden. Es ist der Funktionsparameter, der den Standardwert erhält, nicht die Eigenschaftsinstanz. Die Werbeaktion gilt für denselben Code wie im vorherigen Beispiel.

Vorbehalte

Readonly-Eigenschaften sind eine einfache Syntaxerweiterung, die Sie nach Belieben übernehmen können. Es gibt keine Auswirkungen auf die Abwärtskompatibilität und ihre Verwendung ist völlig optional. Wenn Sie sie hinzufügen, müssen Sie einige Vorbehalte und Einschränkungen beachten.

Im Gegensatz zu regulären Eigenschaften dürfen schreibgeschützte Eigenschaften keinen Standardwert in ihrer Definition haben:

Klasse Demo { protected readonly string $foo = "bar"; }

Diese Anweisung definiert und initialisiert $foo. Sie können ihren Wert nach der Initialisierung nicht ändern, sodass die Eigenschaft praktisch eine Konstante ist. Daher sind Standardwerte verboten und Sie sollten stattdessen eine echte Konstante verwenden:

Klasse Demo { const foo = “bar”; }

Ausgehend von dieser Einschränkung wird Readonly nur für typisierte Eigenschaften unterstützt. Die folgende Eigenschaft hat eine unzulässige Definition:

class Demo { geschützt schreibgeschützt $foo; } Werbung

Eine nicht typisierte Eigenschaft wie $foo oben hat einen impliziten Standardwert von null. Wenn readonly erlaubt war, wird die Option “keine impliziten Konstanten” Regel wieder auftauchen würde. Typisierte Eigenschaften unterscheiden zwischen “nicht initialisiert” und “null” Zustände, so dass sie ohne Wert existieren, bis Sie explizit einen setzen.

Der readonly-Modifizierer hat spezielle Regeln, wenn er als Teil der Klassenvererbung verwendet wird. Untergeordnete Klassen können keine schreibgeschützten Eigenschaften hinzufügen oder entfernen, die von ihren Eltern definiert wurden.

Wenn eine schreibbare Eigenschaft schreibgeschützt ist, würde die übergeordnete Klasse beschädigt, wenn deren Methoden den Wert veränderten. Während das Entfernen der Einschränkung scheinbar harmlos ist, betrachtet RFC schreibgeschützt als “absichtliche Einschränkung” von Fähigkeiten, die verloren gehen würden, wenn Vererbungsüberschreibungen zulässig wären. Es ist verboten, dass Elternklassen behaupten können, dass Kinder keine Nebenwirkungen verursachen können, indem sie Eigenschaften ändern, die schreibgeschützt sein sollen.

Schreibgeschützte Eigenschaften können nur innerhalb des Bereichs festgelegt werden, in dem sie sind definiert. Dies bedeutet, dass öffentliche Eigenschaften nicht von außerhalb einer Klasse festgelegt werden können, auch wenn sie nicht zuvor initialisiert wurden:

Klasse Demo { öffentlicher schreibgeschützter String $foo; }   $d = neue Demo(); $d -> foo = “bar”; //illegal

Die Initialisierung muss innerhalb der Klasse erfolgen, die die Eigenschaft definiert. Infolgedessen ähneln schreibgeschützte Eigenschaften den unveränderlichen Feldern anderer Programmiersprachen im Gegensatz zu bereits vorhandenen PHP-Eigenschaften.

Der readonly-Modifizierer gilt gleichermaßen für alle Schreibvorgänge. Es unterscheidet nicht zwischen internem und externem Zugriff. Sie können keine Eigenschaft haben, die öffentlich schreibgeschützt, aber schreibbar innerhalb der Klasse ist, obwohl eine zukünftige Spezifikationserweiterung dies zulassen könnte.

Werbung

Ein letzter Fallstrick betrifft das Schlüsselwort Clone. Dieser Code funktioniert nicht:

class Demo { öffentliche Funktion __construct( öffentliche Zeichenfolge $foo ) {} }   $d = neue Demo("bar"); $d2 = Klon $d; $d2 -> foo = “foobar”;

Das Klonen folgt denselben Regeln wie der reguläre Zugriff auf Eigenschaften. Obwohl die Änderung in foobar der erste Zugriff auf foo auf $d2 ist, wurde die Property bereits durch den Klonvorgang initialisiert. Während des Klons erfolgt eine implizite Initialisierung.

Wann sollten schreibgeschützte Eigenschaften verwendet werden?

Schreibgeschützte Eigenschaften beschleunigen die Erstellung einfacher Klassen, die Datenstrukturen darstellen, erheblich. Es ist üblich, Wegwerfklassen zu schreiben, um HTTP-Anforderungsparameter, Datenübertragungsobjekte und Antwortdaten aufzunehmen. Diese sind in der Regel unveränderlich, wobei nicht erwartet wird, dass sich Eigenschaften ändern, nachdem die Klasse erstellt wurde.

Früher hatten Sie beim Schreiben strukturähnlicher Klassen zwei unattraktive Möglichkeiten: öffentliche Eigenschaften verwenden, die Entwicklung beschleunigen, aber zulassen ändern, oder verbringen Sie Zeit damit, Getter-Methoden manuell hinzuzufügen, um geschützte Eigenschaften verfügbar zu machen.

//Nicht ideal – Eigenschaften könnten extern geändert werden class UserCreationRequest { öffentliche Funktion __construct( öffentliche Zeichenfolge $Benutzername, öffentliche Zeichenfolge $Passwort ) {} }   //Auch nicht ideal – Viele Boilerplate-Codeklassen UserCreationRequest { öffentliche Funktion __construct( geschützte Zeichenfolge $Benutzername, geschützte Zeichenfolge $Passwort ) {}   öffentliche Funktion getUsername() : Zeichenfolge { Rückgabe $this -> Nutzername; }   öffentliche Funktion getPassword() : Zeichenfolge { Rückgabe $this -> Passwort; } }

Readonly-Eigenschaften ermöglichen endlich den idealen Ansatz:

Klasse UserCreationRequest { öffentliche Funktion __construct( öffentlicher schreibgeschützter String $Benutzername, öffentlicher schreibgeschützter String $Password ) {} }

Die Eigenschaften sind öffentlich zugänglich, aber unveränderlich. In Kombination mit der Promotion von Konstruktor-Eigenschaften versprechen schreibgeschützte Eigenschaften eine deutliche Reduzierung des Boilerplate-Codes, sodass Sie nützliche Klassen schneller schreiben können.

readonly unterstützt auch die Lesbarkeit des Codes und zeigt Ihre Absichten besser an. Jeder, der die UserCreationRequest-Klasse liest oder bearbeitet, weiß, dass ihre Eigenschaften nicht geändert werden sollen. Im ersten Beispiel ist nicht bekannt, ob anderer Code im Projekt die Klasseneigenschaften direkt ändert. Das zweite Beispiel ist etwas klarer, könnte aber dennoch einen Entwickler dazu veranlassen, redundante Methoden setUsername() und setPassword() zu implementieren.

Schlussfolgerung

Der readonly-Modifikator bringt integrierte Unveränderlichkeitsunterstützung für PHP-Klasseneigenschaften. Es macht Ihren Code klarer und verhindert unbeabsichtigte Wertänderungen, indem es Unveränderlichkeit zur Laufzeit erzwingt.

Werbung

Rückblickend auf die PHP 7-Release-Serie, die eine grundlegende strukturähnliche Klasse erstellt, die das Definieren typisierter Eigenschaften umfasst, Schreiben eines Konstruktors, der diese Eigenschaften festlegt, und fügen dann Getter-Methoden hinzu, um ihre Werte verfügbar zu machen. Mit PHP 8.1 können Sie all dies auf eine einzige Konstruktorsignatur komprimieren, indem Sie öffentliche Readonly- und Property-Promotion kombinieren.

Readonly-Eigenschaften werden in den neuesten PHP 8.1-Entwicklungsbuilds implementiert. Die produktionsreife Veröffentlichung wird im November 2021 eintreffen.