Syntaxe de baseclass
Une définition de classe basique commence par le mot-clé
class, suivi du nom de la classe.
Suit une paire d'accolades contenant la définition des propriétés et des
méthodes appartenant à la classe.
Le nom de la classe peut être quelconque à condition que ce ne soit pas un
mot réservé en PHP. Un nom de classe valide commence
par une lettre ou un underscore, suivi de n'importe quel nombre de chiffres, ou de lettres, ou
d'underscores. Si on devait l'exprimer sous forme d'une expression rationnelle, il s'agirait de
^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$.
Une classe peut contenir ses propres constantes,
variables
(appelées "propriétés" ou "attributs"), et fonctions (appelées "méthodes").
Définition typique d'une classe
var;
}
}
?>
]]>
La pseudo-variable $this est disponible
lorsqu'une méthode est appelée depuis un contexte objet.
$this est la valeur de l'objet appelant.
Appeler une méthode non-statique statiquement lance une
Error.
Antérieur à PHP 8.0.0, ceci générait une notice d'obsolescence,
et $this était indéfini.
Quelques exemples de la pseudo-variable $this
foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>
]]>
&example.outputs.7;
&example.outputs.8;
Classes en lecture seule (readonly)
À partir de PHP 8.2.0, une classe peut être marquée
avec le modificateur readonly.
Marquer une classe comme readonly ajoutera
le modificateur readonly
à chaque propriété déclarée, et empêchera la création
de propriétés dynamiques.
En outre, il est impossible d'ajouter leur prise en charge en utilisant
l'attribut AllowDynamicProperties.
Toute tentative de le faire déclenchera une erreur de compilation.
]]>
Comme ni les propriétés non typées ni les propriétés statiques
ne peuvent être marquées avec le modificateur readonly,
les classes readonly ne peuvent pas non plus les déclarer :
]]>
]]>
Une classe readonly peut être
étendu si,
et seulement si, la classe enfant est également
une classe readonly.
Le mot-clé new
Pour créer une instance d'une classe, le mot-clé new doit être
utilisé. Un objet sera alors systématiquement créé, à moins qu'il ait un
constructeur
défini qui lance une exception
en cas d'erreur. Les classes devraient être définies avant l'instanciation (dans
certains cas, c'est impératif).
Si une variable string contenant un nom de classe est utilisée avec
new, une nouvelle instance de cette classe sera créée.
Si la classe est dans un espace de noms, son nom pleinement qualifié doit être utilisé.
S'il n'y a pas d'arguments à passer au constructeur de la classe,
les parenthèses après le nom de la classe peuvent être omises.
Création d'une instance
]]>
À partir de PHP 8.0.0, l'utilisation de new avec des
expressions arbitraires est supportée.
Ceci permet des instantiations plus complexes si l'expression produit une
string. L'expression doit être entourée de parenthèses.
Créer une instance en utilisant une expression arbitraire
Dans l'exemple donné, nous montrons plusieurs exemples d'expressions
arbitraires valides qui produisent un nom de classe.
Ceci montre un appel de fonction, une concaténation de chaînes
et la constante ::class.
]]>
&example.outputs.8;
Dans le contexte de la classe, il est possible de créer un nouvel objet
avec new self et new parent.
Lors de l'assignation d'une instance déjà créée d'une classe à une variable,
la nouvelle variable accédera à la même instance que l'objet qui a été assigné.
Ce comportement est le même lors du passage d'une instance à une fonction.
Une copie d'un objet déjà créé peut être effectuée par
clonage.
Assignation d'un objet
var = '$assigned aura cette valeur';
$instance = null; // $instance et $reference deviennent null
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
]]>
&example.outputs;
string(30) "$assigned aura cette valeur"
}
]]>
Il est possible de créer une instance d'un objet de quelques manières différentes :
Créer de nouveaux objets
]]>
&example.outputs;
Il est possible d'accéder à un membre d'un objet nouvellement
créé en une seule expression :
Accéder un membre d'un objet nouvellement créé
format('Y');
?>
]]>
&example.outputs.similar;
Antérieur à PHP 7.1, les arguments ne sont pas évalués s'il n'y a pas de
fonction constructeur définie.
Propriétés et méthodes
Les propriétés et méthodes de classe vivent dans des "espaces de noms" séparé,
donc il est possible d'avoir une propriété et une méthode avec le même nom.
Faire référence à la fois a une propriété ainsi qu'une méthode ont la même
notation, et le fait qu'une propriété sera accédée ou qu'une méthode sera appelée,
dépend seulement du contexte, c'est-à-dire si l'utilisation est un accès variable
ou un appel de fonction.
Accès de propriété contre appel de méthode
bar, PHP_EOL, $obj->bar(), PHP_EOL;
]]>
&example.outputs;
Ceci signifie qu'appeler une fonction
anonyme qui a été assigné à une propriété n'est pas possible directement.
Au lieu de cela, la propriété doit d'abord être affectée à une variable.
Il est possible d'appeler ce genre de propriété directement
en la mettant entre parenthèses.
Appeler une fonction anonyme enregistrée dans une propriété
bar = function() {
return 42;
};
}
}
$obj = new Foo();
echo ($obj->bar)(), PHP_EOL;
]]>
&example.outputs;
Le mot-clé extends
Une classe peut hériter des constantes, méthodes et des propriétés d'une autre classe en
utilisant le mot-clé extends dans la déclaration.
Il n'est pas possible d'étendre plusieurs classes : une classe peut
uniquement hériter d'une seule classe de base.
Les constantes, méthodes et propriétés héritées peuvent être redéfinies en les redéclarant avec le
même nom que dans la classe parente. Cependant, si la classe parente a défini
une méthode ou constante comme final,
alors celles-ci ne peuvent pas être redéfinies. Il est possible d'accéder aux
méthodes ou propriétés statiques redéfinies en y faisant référence avec l'opérateur
parent::.
À partir de PHP 8.1.0, les constantes peuvent être déclaré comme finale.
Héritage simple d'une classe
displayVar();
?>
]]>
&example.outputs;
Règles de compatibilité de signature
Lors de la surcharge d'une méthode, sa signature doit être compatible avec
la méthode parente. Sinon, une erreur fatale est émise, ou, antérieur à
PHP 8.0.0, une erreur de niveau E_WARNING est générée.
Une signature est compatible si elle respecte les règles de
variance, rend un paramètre
obligatoire optionnel, et seulement si tous les nouveaux paramètres sont
optionnels et assouplissent les régles de visibilité.
Ceci est connu sous le Principe de Substitution de Liskov
(Liskov Substitution Principle), ou simplement LSP.
Le constructeur,
et les méthodes private sont exclus de ces règles de
compatibilité des signatures, et par conséquent n'émettront pas d'erreur
fatale en cas de signature incompatible.
Méthodes enfant compatibles
foo();
$extended2 = new Extend2();
$extended2->foo(1);
]]>
&example.outputs;
Les exemples suivants démontrent qu'une méthode enfant qui supprime un paramètre,
ou rend un paramètre optionnel obligatoire, n'est pas compatible avec la méthode parente.
Erreur fatale quand une méthode enfant supprime un paramètre
&example.outputs.8.similar;
Erreur fatale quand une méthode enfant rend un paramètre optionnel obligatoire
&example.outputs.8.similar;
Renommer un paramètre d'une méthode dans une classe enfant n'est pas
une incompatibilité de signature. Cependant, ceci est découragé car ceci
va résulter en une Error lors du runtime si les
arguments nommés
sont utilisés.
Erreur lors de l'utilisation des arguments nommés et que les paramètres ont été renommés dans une classe enfant
test(foo: "foo", bar: "bar"); // ERROR!
]]>
&example.outputs.similar;
::class
Le mot clé class est également utilisé
pour la résolution des noms de classes.
Il est possible d'obtenir le nom complètement qualifié d'une classe
ClassName en utilisant ClassName::class.
C'est particulièrement utile avec les classes utilisant des
espaces de noms.
Résolution de nom de classe
]]>
&example.outputs;
La résolution du nom de classe en utilisant ::class est une
transformation lors de la compilation. C'est-à-dire à l'instant où la chaine du
nom de classe est créé aucun autochargement n'a encore eu lieu. Par conséquent,
les noms de classes sont étendues même si la classe n'existe pas. Aucune erreur
n'est émise dans ce cas là.
Résolution de nom de classe manquante
]]>
&example.outputs;
À partir de PHP 8.0.0, ::class peut être utilisé
sur les objets. Cette résolution se produit lors de l'exécution, et non lors de
la compilation. Ses effets sont les mêmes que d'appeler
get_class sur l'objet.
Résolution du nom d'un objet
]]>
&example.outputs;
Méthodes et propriétés nullsafe
À partir de PHP 8.0.0, les méthodes et propriétés peuvent aussi être accédés
avec l'opérateur "nullsafe": ?->. L'opérateur nullsafe
fonctionne à l'identique que l'accès de propriétés ou méthodes comme si dessus,
à l'exception que si l'objet qui est déréférencé est &null; alors &null; sera
retourné au lieu de lancer une exception. Si le déréférencement fait par d'une
chaîne, le reste de la chaîne est ignoré.
L'effet est similaire à entourer chaque accès par une vérification avec
is_null d'abord, mais plus compact.
Opérateur nullsafe
getUser(5)?->name;
// Est équivalente à bloc de code suivant :
if (is_null($repository)) {
$result = null;
} else {
$user = $repository->getUser(5);
if (is_null($user)) {
$result = null;
} else {
$result = $user->name;
}
}
?>
]]>
L'opérateur nullsafe est mieux utilisé quand null est considéré une valeur valide
et potentiellement attendu pour une propriété ou valeur de retour d'une méthode.
Pour indiquer une erreur, lancer une exception est préférable.