Så här använder du skrivskyddade egenskaper i PHP 8.1

0
126

PHP 8.1 lägger till stöd för en enbart modifierare på klassegenskaper. En egenskap som är taggad på detta sätt kan bara ställas in en gång. Ett försök att ändra värdet för en enbart egenskap efter initialisering kommer att ge ett fel.

“ Readonly ” är en ganska vag term, med varierande konsekvenser för enskilda programmeringsspråk. I detta sammanhang är “ läsbart ” betyder verkligen att “ oföränderlig ” — du kan ställa in en fastighets värde, men det kan inte ändras efteråt.

Skriva enbart egenskaper

Lägg till enbart modifieraren för att göra en egenskap skrivskyddad. Den bör placeras mellan egenskapens åtkomstmodifierare och dess typhint.

klass Demo { & nbsp; public string $ Mutable; & nbsp; public readonly string $ Immutable; & nbsp; offentlig funktion __konstruera ( string $ Mutable, string $ Immutable ) { & nbsp; $ detta -& gt; Mutable = $ Mutable; $ detta -& gt; Immutable = $ Immutable; } & nbsp; }

$ Mutable är en vanlig allmän egendom. Du kan när som helst ändra dess värde, antingen inom klassmetoder eller utifrån:

$ demo = ny Demo ( & quot; A & quot ;, & quot; X & quot; &#41 ;; $ demo -& gt; Mutable = & quot; B & quot ;;

$ Immutable är lite annorlunda. Du kan fortfarande läsa dess värde när du vill, men eventuella ändringar misslyckas med ett fel:

//Slänger ett fel $ demo -& gt; Immutable = & quot; Y & quot ;; Annons

Den skrivskyddade modifieraren stöds också i främjade konstruktörsegenskaper:

klass Demo { offentlig funktion __konstruera ( public readonly string $ Immutable = & quot; foobar & quot; ) { } }

Du kan fortfarande ställa in fastigheten manuellt i din konstruktör när du använder kampanj med ett standardvärde. Det är funktionsparametern som tar emot standardvärdet, inte egendomsinstansen. Kampanjen försvårar samma kod som visas i det tidigare exemplet.

Varningar

Skrivskyddade egenskaper är en enkel syntaxförbättring som du kan använda på egen hand. Det finns inga konsekvenser för bakåtkompatibilitet, och deras användning är helt valfri. Om du börjar lägga till dem finns det några försiktighetsåtgärder och begränsningar att vara medveten om.

Till skillnad från vanliga egenskaper får skrivskyddade egenskaper inte ha ett standardvärde i definitionen:

klass Demo { skyddad läsbart sträng $ foo = & quot; bar & quot ;; }

Detta uttalande definierar och initierar $ foo. Du kan inte ändra dess värde efter initialisering, så egendomen är faktiskt en konstant. Som ett resultat är standardvärdena förbjudna, och du bör använda en riktig konstant istället:

klass Demo { const foo = & quot; bar & quot ;; }

Till följd av denna begränsning stöds endast skrivskyddade egenskaper. Följande egendom har en olaglig definition:

klass Demo { skyddad läsbart $ foo; } Annons

En ej typad egendom, som $ foo ovan, har ett implicit standardvärde på null. Om det bara var tillåtet, “ inga implicita konstanter ” regel skulle återuppstå. Typade egenskaper skiljer mellan “ oinitialiserade ” och “ null ” stater, så de existerar utan något värde tills du uttryckligen anger ett.

Den skrivskyddade modifieraren har särskilda regler när den används som en del av klassarv. Barnklasser kan inte bara lägga till eller ta bort på egenskaper som definieras av deras föräldrar.

Att göra en skrivbar egenskap läsbart skulle bryta föräldraklassen om dess metoder muterade värdet. Även om avlägsnandet av begränsningen till synes är oskyldigt, ser RFC enbart som en “ avsiktlig begränsning ” kapacitet som skulle gå förlorad om arvsöverträdelser tillåts. Det är förbjudet så att föräldraklasser kan hävda att barn inte kan orsaka biverkningar genom att modifiera egenskaper som är avsedda att vara enbart skrivna.

Egenskaper som endast kan läsas endast inom ramen för de är definierade. Detta innebär att offentliga fastigheter inte kan ställas in utanför en klass, även om de inte har initialiserats tidigare:

klass Demo { public readonly string $ foo; } & nbsp; $ d = ny demo ( &#41 ;; $ d -& gt; foo = & quot; bar & quot ;; //illegal

Initiering måste ske inom klassen som definierar egenskapen. Som ett resultat ligger skrivskyddade egenskaper närmare de oföränderliga fälten för andra programmeringsspråk i motsats till redan existerande PHP-egenskaper.

Den skrivskyddade modifieraren gäller lika för alla skrivningar. Det skiljer inte mellan intern och extern åtkomst. Du kan inte ha en egenskap som är offentligt läsbar men skrivbar inom klassen, även om en framtida spec -tillägg kan tillåta det.

Annonsering

En sista gotcha gäller klonsökordet. Den här koden fungerar inte:

klass Demo { offentlig funktion __konstruera ( offentlig sträng $ foo ) { } } & nbsp; $ d = ny Demo ( & quot; bar & quot; &#41 ;; $ d2 = klon $ d; $ d2 -& gt; foo = & quot; foobar & quot ;;

Kloning följer samma regler som vanlig tillgång till fastigheter. Även om ändringen till foobar är första gången som foo nås på $ d2, har fastigheten redan initierats av kloningsprocessen. Det finns en implicit initialisering under klonen.

När ska man använda Readonly-egenskaper?

Skrivskyddade egenskaper kommer att påskynda skapandet av enkla klasser, som representerar datastrukturer. Det är vanligt att skriva bortkastningsklasser för att hålla HTTP -begärans parametrar, dataöverföringsobjekt och svarsdata. Dessa är vanligtvis oföränderliga, där fastigheter inte förväntas förändras efter att klassen har byggts.

Du hade tidigare två otaliga val när du skrev strukturala klasser: använd offentliga fastigheter, påskynda utvecklingen men tillåt modifiering, eller lägg tid på att lägga till getter -metoder manuellt för att avslöja skyddade egenskaper.

//Inte idealisk – Egenskaper kan ändras externt klass UserCreationRequest { offentlig funktion __konstruera ( public string $ Användarnamn, public string $ Password ) { } } & nbsp; //Inte heller perfekt – Massor av pannkodsklassklass UserCreationRequest { offentlig funktion __konstruera ( skyddad sträng $ Användarnamn, skyddad sträng $ Lösenord ) { } & nbsp; offentlig funktion getUsername ( ) : string { returnera $ detta -& gt; Användarnamn; } & nbsp; offentlig funktion getPassword ( ) : string { returnera $ detta -& gt; Lösenord; } }

Endast enbart egenskaper gör slutligen det ideala tillvägagångssättet möjligt: ​​

klass UserCreationRequest { offentlig funktion __konstruera ( public readonly string $ Användarnamn, public readonly string $ Password ) { } }

Fastigheterna är allmänt tillgängliga men oföränderliga. Kombinerat med konstruktörsegendomskampanjer lovar läsbara fastigheter att minska pannkodskoden betydligt, så att du kan skriva användbara klasser snabbare.

readonly hjälper också kodläsbarhet och indikerar bättre dina avsikter. Alla som läser eller redigerar klassen UserCreationRequest vet att dess egenskaper inte är avsedda att förändras. I det första exemplet är det okänt om annan kod i projektet ändrar klassegenskaperna direkt. Det andra exemplet är lite tydligare, men kan fortfarande få en utvecklare att implementera redundanta setUsername () och setPassword () -metoder.

Slutsats

Skriver endast modifieraren inbyggt oföränderligt stöd för PHP-klassegenskaper. Det gör din kod tydligare och förhindrar oavsiktliga värdeförändringar genom att genomdriva oföränderlighet vid körning.

Annonsering

Ser tillbaka till PHP 7-utgåvorna och skapar en grundläggande strukturliknande klass som används för att definiera typade egenskaper, skriva en konstruktör som anger dessa egenskaper och sedan lägga till getter -metoder för att avslöja deras värden. Med PHP 8.1 kan du komprimera allt detta till en enda konstruktorsignatur genom att kombinera public readonly och fastighetsmarknadsföring.

Readonly -egenskaper implementeras i de senaste PHP 8.1 -utvecklingsbyggnaderna. Det produktionsklara släppet kommer i november 2021.