Files
doc-fr/language/types/declarations.xml
Pierrick Charron db7c8db849 Fix typo
2022-05-26 17:11:04 -04:00

942 lines
25 KiB
XML
Executable File

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: b57f8f256a4773fc09d19733c70ef8816074d12d Maintainer: girgias Status: ready -->
<!-- Reviewed: no -->
<sect1 xml:id="language.types.declarations">
<title>Déclarations de type</title>
<para>
Les déclarations de types peuvent être ajoutées aux arguments des fonctions,
valeurs de retour, et, à partir de PHP 7.4.0, les propriétés de classes.
Elles assurent que les valeurs sont du type spécifié au temps de l'appel,
sinon une <classname>TypeError</classname> est lancée.
</para>
<!-- Find better place where to put this note -->
<!-- TODO Link to covariance section -->
<note>
<para>
Lors de la surcharge d'une méthode parente, la méthode enfant doit correspondre
son type de retour avec la déclaration de type parente. Si le parent ne
définit par de type de retour, la méthode enfant peut en déclarer un.
</para>
</note>
<sect2 xml:id="language.types.declarations.base">
<title>Types unique</title>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>&Type;</entry>
<entry>&Description;</entry>
<entry>&Version;</entry>
</row>
</thead>
<tbody>
<row>
<entry>Nom de classe/interface</entry>
<entry>
La valeur doit être une &instanceof; de la classe ou interface donnée.
</entry>
<entry/>
</row>
<row>
<entry><type>self</type></entry>
<entry>
La valeur doit être une &instanceof; de la même classe que celle
dans laquelle la déclaration de type est utilisée.
Peut uniquement être utilisé dans les classes.
</entry>
<entry/>
</row>
<row>
<entry><type>parent</type></entry>
<entry>
La valeur doit être une &instanceof; du parent de la classe
dans laquelle la déclaration de type est utilisée.
Peut uniquement être utilisé dans les classes.
</entry>
<entry/>
</row>
<row>
<entry><type>array</type></entry>
<entry>
La valeur doit être un tableau (<type>array</type>).
</entry>
<entry/>
</row>
<row>
<entry><type>callable</type></entry>
<entry>
La valeur doit être un <type>callable</type> valide.
Ne peut être utilisé comme déclaration de type de propriété de classe.
</entry>
<entry/>
</row>
<row>
<entry><type>bool</type></entry>
<entry>
La valeur doit être un booléen (<type>bool</type>).
</entry>
<entry/>
</row>
<row>
<entry><type>float</type></entry>
<entry>
La valeur doit être un nombre flottant (<type>float</type>).
</entry>
<entry/>
</row>
<row>
<entry><type>int</type></entry>
<entry>
La valeur doit être un entier (<type>int</type>).
</entry>
<entry/>
</row>
<row>
<entry><type>string</type></entry>
<entry>
La valeur doit être une chaîne de caractères (<type>string</type>).
</entry>
<entry/>
</row>
<row>
<entry><type>iterable</type></entry>
<entry>
La valeur doit être soit un <type>array</type> ou une &instanceof; <classname>Traversable</classname>.
</entry>
<entry>PHP 7.1.0</entry>
</row>
<row>
<entry><type>object</type></entry>
<entry>
La valeur doit être un objet (<type>object</type>).
</entry>
<entry>PHP 7.2.0</entry>
</row>
<row>
<entry><type>mixed</type></entry>
<entry>
La valeur peut être de n'importe quelle valeur.
</entry>
<entry>PHP 8.0.0</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<warning>
<para>
Les alias pour les types scalaires ci-dessus ne sont pas supportés.
À la place, ils sont traités comme des noms de classe ou d'interface.
Par exemple, utiliser <literal>boolean</literal> comme une déclaration de
type nécessite que la valeur soit une &instanceof; de la classe ou
interface <literal>boolean</literal>, plutôt que de type
<type>bool</type> :
</para>
<para>
<example>
<programlisting role="php">
<![CDATA[
<?php
function test(boolean $param) {}
test(true);
?>
]]>
</programlisting>
&example.outputs.8;
<screen>
<![CDATA[
Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2
Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type 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
]]>
</screen>
</example>
</para>
</warning>
<sect3 xml:id="language.types.declarations.mixed">
<title>mixed</title>
<para>
<type>mixed</type> est équivalent au <link linkend="language.types.declarations.composite.union">typ d'union</link>
<type class="union">
<type>object</type><type>resource</type><type>array</type><type>string</type>
<type>int</type><type>float</type><type>bool</type><type>null</type>
</type>.
Disponible à partir de PHP 8.0.0.
</para>
</sect3>
<sect3 xml:id="language.types.declarations.examples">
&reftitle.examples;
<example>
<title>Déclaration de type de classe basique</title>
<programlisting role="php">
<![CDATA[
<?php
class C {}
class D extends C {}
// This doesn't extend C.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
]]>
</programlisting>
&example.outputs.8;
<screen>
<![CDATA[
C
D
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type 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
]]>
</screen>
</example>
<example>
<title>Déclaration de type d'interface basique</title>
<programlisting role="php">
<![CDATA[
<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// This doesn't implement I.
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>
]]>
</programlisting>
&example.outputs.8;
<screen>
<![CDATA[
C
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
Stack trace:
#0 -(13): f(Object(E))
#1 {main}
thrown in - on line 8
]]>
</screen>
</example>
<example>
<title>Déclaration de type de retour basique</title>
<programlisting role="php">
<![CDATA[
<?php
function sum($a, $b): float {
return $a + $b;
}
// Note that a float will be returned.
var_dump(sum(1, 2));
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
float(3)
]]>
</screen>
</example>
<example>
<title>Retournant un objet</title>
<programlisting role="php">
<![CDATA[
<?php
class C {}
function getC(): C {
return new C;
}
var_dump(getC());
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
object(C)#1 (0) {
}
]]>
</screen>
</example>
</sect3>
</sect2>
<sect2 xml:id="language.types.declarations.nullable">
<title>Type nullable</title>
<para>
À partir de PHP 7.1.0, les déclarations de type peuvent être marquées comme
nullable en préfixant le nom du type avec un point d'interrogation
(<literal>?</literal>).
Ceci signifie que la fonction retourne soit le type spécifié soit &null;.
</para>
<para>
<example>
<title>Déclaration de type d'argument nullable</title>
<programlisting role="php">
<![CDATA[
<?php
class C {}
function f(?C $c) {
var_dump($c);
}
f(new C);
f(null);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
object(C)#1 (0) {
}
NULL
]]>
</screen>
</example>
<example>
<title>Déclaration de type de retour nullable</title>
<programlisting role="php">
<![CDATA[
<?php
function get_item(): ?string {
if (isset($_GET['item'])) {
return $_GET['item'];
} else {
return null;
}
}
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
Il est possible d'accomplir des arguments nullable
en définissant la valeur par défaut à <literal>null</literal>.
Ceci n'est pas recommandé, car ceci casse lors de l'héritage.
</para>
<example>
<title>Ancienne façon de rendre un argument nullable</title>
<programlisting role="php">
<![CDATA[
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
object(C)#1 (0) {
}
NULL
]]>
</screen>
</example>
</note>
</sect2>
<sect2 xml:id="language.types.declarations.composite">
<title>Types composés</title>
<para>
Il est possible de combiner des types simples en des types composés.
PHP permet de combiner les types dans les manières suivantes :
</para>
<itemizedlist>
<listitem>
<simpara>
Union de types simples. À partir de PHP 8.0.0.
</simpara>
</listitem>
<listitem>
<simpara>
Intersection des types de classes (noms d'interfaces et de classes). À partir de PHP 8.1.0.
</simpara>
</listitem>
</itemizedlist>
<caution>
<simpara>
Il n'est pas possible de combiner les types d'intersection avec les types d'union.
</simpara>
</caution>
<sect3 xml:id="language.types.declarations.composite.union">
<title>Type d'union</title>
<para>
Une déclaration de type d'union accepte les valeurs de plusieurs types
simples différents, au lieu d'un seul type.
Les types d'union sont spécifiés en utilisant la syntaxe
<literal>T1|T2|...</literal>.
Les types d'union sont disponibles à partir de PHP 8.0.0.
</para>
<sect4 xml:id="language.types.declarations.composite.union.nullable">
<title>Type d'union nullable</title>
<para>
Le type <literal>null</literal> est supporté en tant qu'union, tel que
<literal>T1|T2|null</literal> peut être utilisé pour créer une union nullable.
La notation existante <literal>?T</literal> est considérée comme un raccourci
pour le cas commun <literal>T|null</literal>.
</para>
<caution>
<simpara>
<literal>null</literal> ne peut pas être utilisé comme type autonome.
</simpara>
</caution>
</sect4>
<sect4 xml:id="language.types.declarations.composite.union.false">
<title>Le pseudo-type false</title>
<para>
Le type littéral <literal>false</literal> est supporté en tant qu'union
et est inclus pour des raisons historiques, car beaucoup de fonctions internes
retournent <literal>false</literal> au lieu de <literal>null</literal> en cas
d'échec.
Un exemple classique d'une telle fonction est <function>strpos</function>.
</para>
<caution>
<simpara>
<literal>false</literal> ne peut être utilisé comme type autonome (incluant
un type nullable autonome).
De ce fait, <literal>false</literal>, <literal>false|null</literal>
et <literal>?false</literal> ne sont pas permit.
</simpara>
</caution>
<caution>
<simpara>
Le type littéral <literal>true</literal> n'existe <emphasis>pas</emphasis>.
</simpara>
</caution>
</sect4>
</sect3>
<sect3 xml:id="language.types.declarations.composite.intersection">
<title>Types d'intersection</title>
<para>
Une déclaration de type d'intersection accepte les valeurs qui satisfies
plusieurs déclarations de type de classes, plutôt qu'une seule.
Les types d'intersections sont spécifiés avec la syntaxe <literal>T1&amp;T2&amp;...</literal>.
Les types d'intersections sont disponibles à partir de PHP 8.1.0.
</para>
</sect3>
<sect3 xml:id="language.types.declarations.composite.redundant">
<title>Type redondant et dupliqué</title>
<para>
Pour anticiper des bugs simples dans les déclarations de types composés,
les types redondants qui peuvent être détectés sans effectuer un chargement
des classes résulteront dans une erreur lors de la compilation. Ceci inclus :
<itemizedlist>
<listitem>
<simpara>
Chaque type de nom résolu peut apparaitre qu'une seule fois.
Les types tels que <literal>int|string|INT</literal> ou
<literal>Countable&amp;Traversable&amp;COUNTABLE</literal>
résulteront en une erreur.
</simpara>
</listitem>
<listitem>
<simpara>
Utiliser <type>mixed</type> résultera en une erreur.
</simpara>
</listitem>
<listitem>
<simpara>Pour les types d'union :</simpara>
<itemizedlist>
<listitem>
<simpara>
Si <type>bool</type> est utilisé, <type>false</type> ne peut pas être utilisé additionnellement.
</simpara>
</listitem>
<listitem>
<simpara>
Si <type>object</type> est utilisé, les types de classes ne peuvent pas être utilisés additionnellement.
</simpara>
</listitem>
<listitem>
<simpara>
Si <type>iterable</type> est utilisé, <type>array</type>
et <classname>Traversable</classname> ne peuvent pas être utilisés additionnellement.
</simpara>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<simpara>Pour les types d'intersection :</simpara>
<itemizedlist>
<listitem>
<simpara>
Utiliser un type qui n'est pas un type de classe résultera en une erreur.
</simpara>
</listitem>
<listitem>
<simpara>
Utiliser soit <type>self</type>, <type>parent</type>, ou
<type>static</type> résultera en une erreur.
</simpara>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</para>
<note>
<simpara>
Ceci ne garantie pas que le type soit “minimal”, car faire ainsi nécessiterait
de charger tous les types de classe utilisés.
</simpara>
</note>
<para>
Par exemple, si <literal>A</literal> et <literal>B</literal> sont des alias
de classe, alors <literal>A|B</literal> continue d'être un type d'union
légal, même s'il peut être réduit à soit <literal>A</literal> ou
<literal>B</literal>.
Similairement, si la classe <code>B extends A {}</code>, alors <literal>A|B</literal>
est aussi un type d'union légal, même s'il peut être réduit à juste
<literal>A</literal>.
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function foo(): int|INT {} // Disallowed
function foo(): bool|false {} // Disallowed
function foo(): int&Traversable {} // Disallowed
function foo(): self&Traversable {} // Disallowed
use A as B;
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
function foo(): A&B {} // Disallowed ("use" is part of name resolution)
class_alias('X', 'Y');
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
function foo(): X&Y {} // Allowed (redundancy is only known at runtime)
?>
]]>
</programlisting>
</informalexample>
</para>
</sect3>
</sect2>
<sect2 xml:id="language.types.declarations.return-only">
<title>Type uniquement valide comme type de retour</title>
<sect3 xml:id="language.types.declarations.void">
<title>void</title>
<para>
<literal>void</literal> est un type de retour indiquant que la fonction
ne retourne pas de valeur.
Ainsi il ne peut pas faire partie d'une déclaration de type d'union.
Disponible à partir de PHP 7.1.0.
</para>
<note>
<para>
Retourner par référence d'une fonction <type>void</type> est obsolète à
partir de PHP 8.1.0, car une telle fonction est contradictoire.
Auparavant, ceci émettait déjà la <constant>E_NOTICE</constant>
suivante quand appelé :
<literal>Only variable references should be returned by reference</literal>.
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function &test(): void {}
?>
]]>
</programlisting>
</informalexample>
</para>
</note>
</sect3>
<sect3 xml:id="language.types.declarations.never">
<title>never</title>
<para>
<literal>never</literal> est un type de retour indiquant que la fonction ne
retourne pas. Ceci signifie que soit elle appelle <function>exit</function>,
lance une exception, ou est une boucle infinie.
Par conséquent, ceci ne peut pas prendre part à une déclaration de type d'union.
Disponible à partir de PHP 8.1.0.
</para>
<para>
<type>never</type> est, en parlance de théorie des types, le type vide.
Signifiant que c'est le sous-type de tout autre type et peut remplacer
tout type de retour lors de l'héritage.
</para>
</sect3>
<sect3 xml:id="language.types.declarations.static">
<title>static</title>
<para>
La valeur doit être une &instanceof; de la même classe que celle où la
méthode est appelée.
Disponible à partir de PHP 8.0.0.
</para>
</sect3>
</sect2>
<sect2 xml:id="language.types.declarations.strict">
<title>Typage Strict</title>
<para>
Par défaut, PHP va convertir les valeurs d'un mauvais type vers le type
scalaire attendu tant que possible. Par exemple, une fonction, qui attend
comme paramètre une <type>string</type>, à laquelle est passée un
<type>int</type> recevra une variable de type <type>string</type>.
</para>
<para>
Il est possible d'activer le mode de typage strict fichier par fichier.
Dans le mode strict, seule une variable correspondant exactement au
type attendu dans la déclaration sera acceptée sinon une
<classname>TypeError</classname> sera levée.
La seule exception à cette règle est qu'une valeur de type <type>int</type>
peut passer une déclaration de type <type>float</type>.
</para>
<warning>
<simpara>
Les appels aux fonctions depuis des fonctions internes ne seront pas
affectés par la déclaration <literal>strict_types</literal>.
</simpara>
</warning>
<para>
Pour activer le mode strict, l'expression &declare; est utilisée avec la
déclaration <literal>strict_types</literal> :
</para>
<note>
<para>
Le typage strict s'applique aux appels de fonction effectués depuis
<emphasis>l'intérieur</emphasis> d'un fichier dont le typage strict est
actif, et non aux fonctions déclarées dans ce fichier. Si un fichier dont
le typage strict n'est pas activé effectue un appel à une fonction qui a
été définie dans un fichier dont le type strict est actif, la préférence de
l'appelant (mode coercitif) sera respecté et la valeur sera forcée.
</para>
</note>
<note>
<para>
Le typage strict n'est défini que pour les déclarations de type scalaire.
</para>
</note>
<example>
<title>Typage strict pour les valeurs d'arguments</title>
<programlisting role="php">
<![CDATA[
<?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));
?>
]]>
</programlisting>
&example.outputs.8;
<screen>
<![CDATA[
int(3)
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type 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
]]>
</screen>
</example>
<example>
<title>Typage coercitif pour les valeurs d'arguments</title>
<programlisting role="php">
<![CDATA[
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// These will be coerced to integers: note the output below!
var_dump(sum(1.5, 2.5));
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
int(3)
int(3)
]]>
</screen>
</example>
<example>
<title>Typage strict pour les valeurs de retour</title>
<programlisting role="php">
<![CDATA[
<?php
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
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
]]>
</screen>
</example>
</sect2>
<sect2 xml:id="language.types.declarations.union.coercive">
<title>Typage coercitif avec les types d'union</title>
<para>
Quand <literal>strict_types</literal> n'est pas activé, les déclarations de
types scalaire sont sujets à des coercitions de type implicite limité.
Si le type exact de la valeur ne fait pas partie de l'union, alors le type
cible est choisie dans l'ordre de préférence suivant :
<orderedlist>
<listitem>
<simpara>
</simpara>
</listitem>
<listitem>
<simpara>
<type>float</type>
</simpara>
</listitem>
<listitem>
<simpara>
<type>string</type>
</simpara>
</listitem>
<listitem>
<simpara>
<type>bool</type>
</simpara>
</listitem>
</orderedlist>
Si le type existe dans l'union, et que la valeur peut être forcée dans le
type sous les sémantiques existantes de vérification de type de PHP, alors
le type est choisi. Sinon le prochain type est essayé.
</para>
<caution>
<para>
Il y a une exception, si la valeur est une chaîne de caractère et que
<type>int</type> et <type>float</type> font partie de l'union, alors le
type préféré est choisie en fonction des sémantiques de “chaîne numérique”.
Par exemple, pour <literal>"42"</literal> <type>int</type> est choisie,
tant que pour <literal>"42.0"</literal> <type>float</type> est choisie.
</para>
</caution>
<note>
<para>
Les types qui ne font pas partie de la liste de préférence ci-dessus ne
sont pas des cibles éligibles aux coercitions implicites. En particulier
aucune coercition implicite aux types <literal>null</literal> et
<literal>false</literal> se produit.
</para>
</note>
<example>
<title>Exemple de types étant forcé dans le type faisant partie de l'union</title>
<programlisting role="php">
<![CDATA[
<?php
// int|string
42 --> 42 // exact type
"42" --> "42" // exact type
new ObjectWithToString --> "Result of __toString()"
// object never compatible with int, fall back to string
42.0 --> 42 // float compatible with int
42.1 --> 42 // float compatible with int
1e100 --> "1.0E+100" // float too large for int type, fall back to string
INF --> "INF" // float too large for int type, fall back to string
true --> 1 // bool compatible with int
[] --> TypeError // array not compatible with int or string
// int|float|bool
"45" --> 45 // int numeric string
"45.0" --> 45.0 // float numeric string
"45X" --> true // not numeric string, fall back to bool
"" --> false // not numeric string, fall back to bool
"X" --> true // not numeric string, fall back to bool
[] --> TypeError // array not compatible with int, float or bool
?>
]]>
</programlisting>
</example>
</sect2>
<!-- TODO figure out what do to with these things -->
<sect2 xml:id="language.types.declarations.misc">
<title>Divers</title>
<example>
<title>Paramètre typé passé par référence</title>
<simpara>
Les types déclarés des références des paramètres sont vérifiés lors de l'entrée
dans la fonction, mais pas lorsque la fonction retourne, donc après que la
fonction a retourné, le type de l'argument a pu être modifié.
</simpara>
<programlisting role="php">
<![CDATA[
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
]]>
</programlisting>
&example.outputs.8;
<screen>
<![CDATA[
int(1)
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type 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
]]>
</screen>
</example>
<example>
<title>Capturer l'exception de type <classname>TypeError</classname></title>
<programlisting role="php">
<![CDATA[
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
try {
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
} catch (TypeError $e) {
echo 'Error: ', $e->getMessage();
}
?>
]]>
</programlisting>
&example.outputs.8;
<screen>
<![CDATA[
int(3)
Error: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 10
]]>
</screen>
</example>
</sect2>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->