Par défaut, les cas énumérés n'ont pas d'équivalent scalaire. Il s'agit simplement d'objets singleton. Cependant, il existe de nombreux cas où un cas énuméré doit être capable de faire des allers-retours vers une base de données ou entrepôt de données similaire. Il est donc utile d'avoir un équivalent scalaire intégré (et donc trivialement sérialisable) défini intrinsèquement.
Pour définir un équivalent scalaire pour une énumération, la syntaxe est la suivante :
<?php
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
?>
Un cas qui a un équivalent scalaire est appelé un cas soutenu ou "Backed Case", car il est "soutenu" par une valeur plus simple. Une énumération qui contient uniquement des cas soutenus est appelée "énumération soutenue" ou "Backed Enum". Une Enum soutenue ne peut contenir que des cas soutenus. Une Enum pure ne peut contenir que des cas purs.
Une Enum soutenue peut être soutenue par des types int
ou string
,
et une énumération donnée ne supporte qu'un seul type à la fois (c'est-à-dire pas d'union de int|string
).
Si une énumération est marquée comme ayant un équivalent scalaire, tous les cas doivent avoir un équivalent scalaire
unique défini explicitement. Il n'y a pas d'équivalents scalaires auto-générés
(par exemple, des entiers séquentiels). Les cas soutenus doivent être uniques ; deux cas enum soutenus
ne peuvent pas avoir le même équivalent scalaire. Cependant, une constante peut faire référence à un
cas, créant ainsi un alias. Voir Constantes d'énumération.
Les valeurs équivalentes doivent être des littéraux ou des expressions littérales. Les constantes et les expressions constantes
ne sont pas prises en charge. Autrement dit, 1 + 1
est autorisé, mais 1 + SOME_CONST
ne l'est pas.
Les cas soutenus ont une propriété supplémentaire en lecture seule, value
, qui est la valeur
spécifiée dans la définition.
<?php
print Suit::Clubs->value;
// Prints "C"
?>
Afin d'enforcer la propriété value
en lecture seule, une variable ne peut pas
être assignée en tant que référence à cette propriété. En d'autres termes, l'opération suivante entraîne une erreur:
<?php
$suit = Suit::Clubs;
$ref = &$suit->value;
// Error: Cannot acquire reference to property Suit::$value
?>
Les enums soutenues implémentent une interface interne BackedEnum, qui expose deux méthodes supplémentaires :
from(int|string): self
prend un scalaire et renvoie le cas d'Enum
correspondant. S'il n'en trouve pas, il lèvera une ValueError. Ceci est principalement
utile dans les cas où le scalaire en entrée est fiable et où une valeur d'enum manquante devrait être
considérée comme une erreur qui arrête l'application.
tryFrom(int|string): ?self
prend un scalaire et renvoie le
cas d'Enum correspondant. S'il n'en trouve pas, il retournera null
.
Ceci est principalement utile dans les cas où le scalaire en entrée n'est pas fiable et que l'appelant souhaite
implémenter sa propre gestion d'erreur ou sa logique de valeur par défaut.
Les méthodes from()
et tryFrom()
suivent les règles
standard de typage faible/fort. En mode de typage faible, il est possible de passer un entier ou une chaîne de caractères.
et le système forcera la valeur en conséquence. Le passage d'un flottant fonctionnera également et sera
coercitif. En mode de typage strict, passer un entier à from()
sur une enum soutenue
par une chaîne de caractères (ou vice versa) entraînera une erreur de type (TypeError),
tout comme un float dans toutes les circonstances. Tous les autres types de paramètres provoqueront une TypeError
dans les deux modes.
<?php
$record = get_stuff_from_database($id);
print $record['suit'];
$suit = Suit::from($record['suit']);
// Invalid data throws a ValueError: "X" is not a valid scalar value for enum "Suit"
print $suit->value;
$suit = Suit::tryFrom('A') ?? Suit::Spades;
// Invalid data returns null, so Suit::Spades is used instead.
print $suit->value;
?>
La définition manuelle d'une méthode from()
ou tryFrom()
sur une énumération soutenue entraîne une erreur fatale.