Typdeklarationer: Skillnad mellan sidversioner
Admin (diskussion | bidrag) |
Admin (diskussion | bidrag) Ingen redigeringssammanfattning |
||
Rad 314: | Rad 314: | ||
#1 {main} | #1 {main} | ||
thrown in - on line 8 | thrown in - on line 8 | ||
== Strikt typning == | |||
Som standard kommer PHP att konvertera värden av fel typ till den förväntade skalära typdeklarationen om möjligt. Till exempel, om en funktion ges ett heltal för en parameter som förväntar sig en sträng, kommer den att få en variabel av typen sträng. | |||
Det är möjligt att aktivera strikt läge på en fil-för-fil basis. I strikt läge accepteras endast ett värde som exakt motsvarar typdeklarationen, annars kastas ett ''TypeError''. Det enda undantaget från denna regel är att ett heltalsvärde kommer att passera en flyttals typdeklaration. | |||
'''Varning''' | |||
Funktionsanrop inom interna funktioner påverkas inte av ''strict_types''-deklarationen. | |||
För att aktivera strikt läge används ''declare''-satsen med ''strict_types''-deklarationen: | |||
'''Notera:''' | |||
Strikt typning gäller för funktionsanrop som görs inifrån filen där strikt typning är aktiverat, inte för funktionerna som deklareras inom den filen. Om en fil utan strikt typning aktiverat gör ett anrop till en funktion som definierats i en fil med strikt typning, kommer anroparens preferens (koerciv typning) att respekteras, och värdet kommer att konverteras. | |||
'''Notera:''' | |||
Strikt typning är endast definierad för skalära typdeklarationer. | |||
'''Exempel #10 Strikt typning för argumentvärden''' | |||
<code> | |||
<?php | |||
declare(strict_types=1); | |||
function sum(int $a, int $b) { | |||
return $a + $b; | |||
} | |||
var_dump(sum(1, 2)); | |||
var_dump(sum(1.5, 2.5)); | |||
?> | |||
</code> | |||
Output av ovanstående exempel i PHP 8: | |||
int(3) | |||
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) måste vara av typ int, float given, called in - on line 9 and defined in -:4 | |||
Stack trace: | |||
#0 -(9): sum(1.5, 2.5) | |||
#1 {main} | |||
thrown in - on line 4 | |||
'''Exempel #11 Koerciv typning för argumentvärden''' | |||
<code> | |||
<?php | |||
function sum(int $a, int $b) { | |||
return $a + $b; | |||
} | |||
var_dump(sum(1, 2)); | |||
// Dessa kommer att omvandlas till heltal: observera utdata nedan! | |||
var_dump(sum(1.5, 2.5)); | |||
?> | |||
</code> | |||
Ovanstående exempel kommer att ge utdata: | |||
int(3) | |||
int(3) | |||
'''Exempel #12 Strikt typning för returvärden''' | |||
<code> | |||
<?php | |||
declare(strict_types=1); | |||
function sum($a, $b): int { | |||
return $a + $b; | |||
} | |||
var_dump(sum(1, 2)); | |||
var_dump(sum(1, 2.5)); | |||
?> | |||
</code> | |||
Ovanstående exempel kommer att ge utdata: | |||
int(3) | |||
Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5 | |||
Stack trace: | |||
#0 -(9): sum(1, 2.5) | |||
#1 {main} | |||
thrown in - on line 5 | |||
[[PHP]] | [[PHP]] | ||
[[Språkreferens]] | [[Språkreferens]] | ||
[[Kategori:Php]] | [[Kategori:Php]] |
Nuvarande version från 14 augusti 2024 kl. 05.46
Typdeklarationer
Typdeklarationer kan läggas till funktionsargument, returvärden och, från och med PHP 7.4.0, klassens egenskaper. De säkerställer att värdet är av den specificerade typen vid anropstid, annars kastas ett TypeError.
Varje enskild typ som PHP stöder, med undantag av resource, kan användas inom användarlandstypdeklarationer. Denna sida innehåller en ändringslogg för tillgängligheten av de olika typerna och dokumentation om hur man använder dem i typdeklarationer.
Notera:
När en klass implementerar en interfacemetod eller återimplementerar en metod som redan definierats av en föräldraklass, måste den vara kompatibel med den tidigare definitionen. En metod är kompatibel om den följer variansreglerna.
Ändringslogg
Version | Beskrivning |
---|---|
8.3.0 | Stöd för klass, interface, trait, och enum konstant typning har lagts till. |
8.2.0 | Stöd för DNF-typer har lagts till. |
8.2.0 | Stöd för den litterala typen true har lagts till. |
8.2.0 | Typerna null och false kan nu användas enskilt. |
8.1.0 | Stöd för snitttyper har lagts till. |
8.1.0 | Att returnera med referens från en void-funktion är nu föråldrat. |
8.1.0 | Stöd för returtypen never har lagts till. |
8.0.0 | Stöd för mixed har lagts till. |
8.0.0 | Stöd för returtypen static har lagts till. |
8.0.0 | Stöd för unionstyper har lagts till. |
7.4.0 | Stöd för typning av klassens egenskaper har lagts till. |
7.2.0 | Stöd för object har lagts till. |
7.1.0 | Stöd för iterable har lagts till. |
7.1.0 | Stöd för void har lagts till. |
7.1.0 | Stöd för nullable typer har lagts till. |
Användning av atomtyper
Atomtyper har ett rakt fram beteende med några mindre varningar som beskrivs i detta avsnitt.
Skalära typer
Varning Namnalias för skalära typer (bool, int, float, string) stöds inte. Istället behandlas de som klass- eller gränssnittsnamn. Till exempel, att använda boolean som en typdeklaration kommer att kräva att värdet är en instans av klassen eller gränssnittet boolean, snarare än av typen bool:
<?php
function test(boolean $param) {}
test(true);
?>
Output av ovanstående exempel i PHP 8:
Varning: "boolean" kommer att tolkas som ett klassnamn. Menade du "bool"? Skriv "\boolean" för att undertrycka denna varning på rad 2
Fatal error: Uncaught TypeError: test(): Argument #1 ($param) måste vara av typen boolean, bool given, called in - on line 3 and defined in -:2 Stack trace:
- 0 -(3): test(true)
- 1 {main}
thrown in - on line 2
void
Notera: Att returnera med referens från en void-funktion är föråldrat från och med PHP 8.1.0, eftersom en sådan funktion är motsägelsefull. Tidigare genererade den följande E_NOTICE när den kallades: Endast variabelreferenser bör returneras med referens.
<?php
function &test(): void {}
?>
Anropbara typer
Denna typ kan inte användas som en klass egendoms typdeklaration.
Notera: Det är inte möjligt att specificera funktionens signatur.
Typdeklarationer på parametrar som överförs via referens
Om en parameter som överförs via referens har en typdeklaration, kontrolleras typen av variabeln endast vid funktionens ingång, i början av anropet, men inte när funktionen returnerar. Detta innebär att en funktion kan ändra typen av variabelreferens.
Exempel #1 Typade parametrar som överförs via referens
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
Det ovanstående exemplet kommer att ge något liknande:
int(1)
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) måste vara av typ array, int given, called in - on line 9 and defined in -:2 Stack trace:
- 0 -(9): array_baz(1)
- 1 {main}
thrown in - on line 2
Användningsanteckningar för sammansatta typer
Sammansatta typdeklarationer är föremål för ett par begränsningar och kommer att utföra en redundanskontroll vid kompileringstid för att förhindra enkla buggar.
Försiktighet Före PHP 8.2.0, och införandet av DNF-typer, var det inte möjligt att kombinera snitttyper med unionstyper.
Unionstyper
Varning Det är inte möjligt att kombinera de två värde typerna false och true tillsammans i en unionstyp. Använd bool istället.
Försiktighet Före PHP 8.2.0, eftersom false och null inte kunde användas som fristående typer, var en unionstyp som endast bestod av dessa typer inte tillåten. Detta omfattar följande typer: false, false|null och ?false.
Nullable typ syntaktiskt socker
En enda bas typdeklaration kan markeras som nullable genom att prefixa typen med ett frågetecken (?). Således är ?T och T|null identiska.
Notera: Denna syntax stöds från och med PHP 7.1.0 och föregår stöd för generaliserade unionstyper.
Notera:
Det är också möjligt att uppnå nullable argument genom att göra null till standardvärdet. Detta rekommenderas inte eftersom om standardvärdet ändras i en underklass kan en typkompatibilitetsöverträdelse uppstå eftersom nulltypen måste läggas till i typdeklarationen.
Exempel #2 Gammalt sätt att göra argument nullable
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>
Det ovanstående exemplet kommer att ge ut:
object(C)#1 (0) {} NULL
void
Notera: Att returnera med referens från en void-funktion är föråldrat från och med PHP 8.1.0, eftersom en sådan funktion är motsägelsefull. Tidigare genererade den följande E_NOTICE när den kallades: Endast variabelreferenser bör returneras med referens.
<?php
function &test(): void {}
?>
Anropbara typer
Denna typ kan inte användas som en klass egendoms typdeklaration.
Notera: Det är inte möjligt att specificera funktionens signatur.
Typdeklarationer på parametrar som överförs via referens
Om en parameter som överförs via referens har en typdeklaration, kontrolleras typen av variabeln endast vid funktionens ingång, i början av anropet, men inte när funktionen returnerar. Detta innebär att en funktion kan ändra typen av variabelreferens.
Exempel #1 Typade parametrar som överförs via referens
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
Det ovanstående exemplet kommer att ge något liknande:
int(1)
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) måste vara av typ array, int given, called in - on line 9 and defined in -:2 Stack trace:
- 0 -(9): array_baz(1)
- 1 {main}
thrown in - on line 2
Användningsanteckningar för sammansatta typer
Sammansatta typdeklarationer är föremål för ett par begränsningar och kommer att utföra en redundanskontroll vid kompileringstid för att förhindra enkla buggar.
Försiktighet Före PHP 8.2.0, och införandet av DNF-typer, var det inte möjligt att kombinera snitttyper med unionstyper.
Unionstyper
Varning Det är inte möjligt att kombinera de två värde typerna false och true tillsammans i en unionstyp. Använd bool istället.
Försiktighet Före PHP 8.2.0, eftersom false och null inte kunde användas som fristående typer, var en unionstyp som endast bestod av dessa typer inte tillåten. Detta omfattar följande typer: false, false|null och ?false.
Nullable typ syntaktiskt socker
En enda bas typdeklaration kan markeras som nullable genom att prefixa typen med ett frågetecken (?). Således är ?T och T|null identiska.
Notera: Denna syntax stöds från och med PHP 7.1.0 och föregår stöd för generaliserade unionstyper.
Notera:
Det är också möjligt att uppnå nullable argument genom att göra null till standardvärdet. Detta rekommenderas inte eftersom om standardvärdet ändras i en underklass kan en typkompatibilitetsöverträdelse uppstå eftersom nulltypen måste läggas till i typdeklarationen.
Exempel #2 Gammalt sätt att göra argument nullable
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>
Det ovanstående exemplet kommer att ge ut:
object(C)#1 (0) {} NULL
Duplicerade och Redundanta Typer
För att fånga enkla buggar i sammansatta typdeklarationer kommer redundanta typer som kan upptäckas utan att utföra klassinläsning att resultera i ett kompileringsfel. Detta inkluderar:
Varje namnupplöst typ får endast förekomma en gång. Typer som int|string|INT eller Countable&Traversable&COUNTABLE resulterar i ett fel.
Användning av mixed resulterar i ett fel. För unionstyper: Om bool används, kan false eller true inte användas ytterligare. Om object används, kan inte klass typer användas ytterligare. Om iterable används, kan inte array och Traversable användas ytterligare. För snitttyper:
Användning av en typ som inte är en klass-typ resulterar i ett fel. Användning av antingen self, parent, eller static resulterar i ett fel.
För DNF-typer:
Om en mer generisk typ används, är den mer restriktiva en redundant. Användning av två identiska snitttyper.
Notera: Detta garanterar inte att typen är ”minimal”, eftersom detta skulle kräva att alla använda klass typer laddas.
Till exempel, om A och B är klassalias, så förblir A|B en laglig unionstyp, även om den kunde reduceras till antingen A eller B. På samma sätt, om klass B ärver från A {}, så är A|B också en laglig unionstyp, även om den kunde reduceras till bara A.
<?php
function foo(): int|INT {} // Ej tillåtet
function foo(): bool|false {} // Ej tillåtet
function foo(): int&Traversable {} // Ej tillåtet
function foo(): self&Traversable {} // Ej tillåtet
use A as B;
function foo(): A|B {} // Ej tillåtet ("use" är en del av namnupplösningen)
function foo(): A&B {} // Ej tillåtet ("use" är en del av namnupplösningen)
class_alias('X', 'Y');
function foo(): X|Y {} // Tillåtet (redundans är endast känd vid körning)
function foo(): X&Y {} // Tillåtet (redundans är endast känd vid körning)?>
Exempel #3 Grundläggande klass typdeklaration
<?php
class C {}
class D extends C {}// Detta utökar inte C.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
Output av ovanstående exempel i PHP 8:
C
D
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) måste vara av typ C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8 Stack trace:
- 0 -(14): f(Object(E))
- 1 {main}
thrown in - on line 8
Strikt typning
Som standard kommer PHP att konvertera värden av fel typ till den förväntade skalära typdeklarationen om möjligt. Till exempel, om en funktion ges ett heltal för en parameter som förväntar sig en sträng, kommer den att få en variabel av typen sträng.
Det är möjligt att aktivera strikt läge på en fil-för-fil basis. I strikt läge accepteras endast ett värde som exakt motsvarar typdeklarationen, annars kastas ett TypeError. Det enda undantaget från denna regel är att ett heltalsvärde kommer att passera en flyttals typdeklaration.
Varning Funktionsanrop inom interna funktioner påverkas inte av strict_types-deklarationen.
För att aktivera strikt läge används declare-satsen med strict_types-deklarationen:
Notera: Strikt typning gäller för funktionsanrop som görs inifrån filen där strikt typning är aktiverat, inte för funktionerna som deklareras inom den filen. Om en fil utan strikt typning aktiverat gör ett anrop till en funktion som definierats i en fil med strikt typning, kommer anroparens preferens (koerciv typning) att respekteras, och värdet kommer att konverteras.
Notera: Strikt typning är endast definierad för skalära typdeklarationer.
Exempel #10 Strikt typning för argumentvärden
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>
Output av ovanstående exempel i PHP 8:
int(3)
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) måste vara av typ int, float given, called in - on line 9 and defined in -:4 Stack trace:
- 0 -(9): sum(1.5, 2.5)
- 1 {main}
thrown in - on line 4
Exempel #11 Koerciv typning för argumentvärden
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// Dessa kommer att omvandlas till heltal: observera utdata nedan!
var_dump(sum(1.5, 2.5));
?>
Ovanstående exempel kommer att ge utdata:
int(3) int(3) Exempel #12 Strikt typning för returvärden
<?php
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>
Ovanstående exempel kommer att ge utdata:
int(3)
Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5 Stack trace:
- 0 -(9): sum(1, 2.5)
- 1 {main}
thrown in - on line 5