mirror of
https://github.com/macintoshplus/doc-fr.git
synced 2026-03-26 01:42:09 +01:00
514 lines
12 KiB
XML
514 lines
12 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: afec339bc5b7918baddd9ba3cd02b90f3b423230 Maintainer: yannick Status: ready -->
|
|
<!-- Reviewed: no Maintainer: itanea -->
|
|
<sect1 xml:id="language.oop5.traits" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Traits</title>
|
|
<para>
|
|
PHP implémente une manière pour réutiliser du code appelée Traits.
|
|
</para>
|
|
<para>
|
|
Les traits sont un mécanisme de réutilisation de code dans un langage à héritage simple
|
|
tel que PHP. Un trait tente de réduire certaines limites de l'héritage simple, en autorisant
|
|
le développeur à réutiliser un certain nombre de méthodes dans des classes indépendantes.
|
|
La sémantique entre les classes et les traits réduit la complexité et évite les problèmes
|
|
typiques de l'héritage multiple et des Mixins.
|
|
</para>
|
|
<para>
|
|
Un trait est semblable à une classe, mais il ne sert qu'à grouper des fonctionnalités d'une
|
|
manière intéressante. Il n'est pas possible d'instancier un Trait en lui-même. C'est un
|
|
ajout à l'héritage traditionnel, qui autorise la composition horizontale de comportements,
|
|
c'est à dire l'utilisation de méthodes de classe sans besoin d'héritage.
|
|
</para>
|
|
|
|
<example xml:id="language.oop5.traits.basicexample">
|
|
<title>Exemple d'utilisation de Trait</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait ezcReflectionReturnInfo {
|
|
function getReturnType() { /*1*/ }
|
|
function getReturnDescription() { /*2*/ }
|
|
}
|
|
|
|
class ezcReflectionMethod extends ReflectionMethod {
|
|
use ezcReflectionReturnInfo;
|
|
/* ... */
|
|
}
|
|
|
|
class ezcReflectionFunction extends ReflectionFunction {
|
|
use ezcReflectionReturnInfo;
|
|
/* ... */
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<sect2 xml:id="language.oop5.traits.precedence">
|
|
<title>Précédence</title>
|
|
<para>
|
|
Une méthode héritée depuis une classe mère est écrasée par une méthode issue d'un Trait.
|
|
L'ordre de précédence fait en sorte que les méthodes de la classe courante
|
|
écrasent les méthodes issues d'un Trait, elles-mêmes surchargeant les méthodes héritées.
|
|
</para>
|
|
<example xml:id="language.oop5.traits.precedence.examples.ex1">
|
|
<title>Exemple avec l'ordre de précédence</title>
|
|
<para>
|
|
Une méthode héritée depuis la classe de base est écrasée par celle provenant
|
|
du Trait. Ce n'est pas le cas des méthodes réelles, écrites dans la classe de base.
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Base {
|
|
public function sayHello() {
|
|
echo 'Hello ';
|
|
}
|
|
}
|
|
|
|
trait SayWorld {
|
|
public function sayHello() {
|
|
parent::sayHello();
|
|
echo 'World!';
|
|
}
|
|
}
|
|
|
|
class MyHelloWorld extends Base {
|
|
use SayWorld;
|
|
}
|
|
|
|
$o = new MyHelloWorld();
|
|
$o->sayHello();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Hello World!
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example xml:id="language.oop5.traits.precedence.examples.ex2">
|
|
<title>Autre exemple d'ordre de précédence</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait HelloWorld {
|
|
public function sayHello() {
|
|
echo 'Hello World!';
|
|
}
|
|
}
|
|
|
|
class TheWorldIsNotEnough {
|
|
use HelloWorld;
|
|
public function sayHello() {
|
|
echo 'Hello Universe!';
|
|
}
|
|
}
|
|
|
|
$o = new TheWorldIsNotEnough();
|
|
$o->sayHello();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Hello Universe!
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.traits.multiple">
|
|
<title>Multiples Traits</title>
|
|
<para>
|
|
Une classe peut utiliser de multiples Traits en les déclarant avec le
|
|
mot-clé <literal>use</literal>, séparés par des virgules.
|
|
</para>
|
|
<example xml:id="language.oop5.traits.multiple.ex1">
|
|
<title>Utilisation de plusieurs Traits</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait Hello {
|
|
public function sayHello() {
|
|
echo 'Hello ';
|
|
}
|
|
}
|
|
|
|
trait World {
|
|
public function sayWorld() {
|
|
echo 'World';
|
|
}
|
|
}
|
|
|
|
class MyHelloWorld {
|
|
use Hello, World;
|
|
public function sayExclamationMark() {
|
|
echo '!';
|
|
}
|
|
}
|
|
|
|
$o = new MyHelloWorld();
|
|
$o->sayHello();
|
|
$o->sayWorld();
|
|
$o->sayExclamationMark();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Hello World!
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.traits.conflict">
|
|
<title>Résolution des conflits</title>
|
|
<para>
|
|
Si deux Traits insèrent une méthode avec le même nom, une erreur fatale est levée si le conflit n'est
|
|
pas explicitement résolu.
|
|
</para>
|
|
<para>
|
|
Pour résoudre un conflit de nommage entre des Traits utilisés dans la même classe, il faut utiliser l'opérateur
|
|
<literal>insteadof</literal> pour choisir une des méthodes en conflit.
|
|
</para>
|
|
<para>
|
|
Puisque ce principe ne permet que d'exclure des méthodes,
|
|
l'opérateur <literal>as</literal> peut être utilisé pour permettre
|
|
l'inclusion d'une des méthodes conflictuelles sous un autre nom. Notez que
|
|
l'opérateur <literal>as</literal> ne renomme pas la méthode et n'affecte pas
|
|
d'autres méthodes non plus.
|
|
</para>
|
|
<example xml:id="language.oop5.traits.examples.ex1">
|
|
<title>Résolution des conflits</title>
|
|
<para>
|
|
Dans cet exemple, la classe Talker utilise les traits A et B.
|
|
Comme A et B ont des méthodes conflictuelles, on indique que l'on souhaite utiliser
|
|
la variante de smallTalk depuis le trait B, et la variante de bigTalk depuis le
|
|
trait A.
|
|
</para>
|
|
<para>
|
|
La classe Aliased_Talker utilise l'opérateur <literal>as</literal>
|
|
pour être capable d'utiliser l'implémentation bigTalk de B sous un alias
|
|
supplémentaire <literal>talk</literal>.
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait A {
|
|
public function smallTalk() {
|
|
echo 'a';
|
|
}
|
|
public function bigTalk() {
|
|
echo 'A';
|
|
}
|
|
}
|
|
|
|
trait B {
|
|
public function smallTalk() {
|
|
echo 'b';
|
|
}
|
|
public function bigTalk() {
|
|
echo 'B';
|
|
}
|
|
}
|
|
|
|
class Talker {
|
|
use A, B {
|
|
B::smallTalk insteadof A;
|
|
A::bigTalk insteadof B;
|
|
}
|
|
}
|
|
|
|
class Aliased_Talker {
|
|
use A, B {
|
|
B::smallTalk insteadof A;
|
|
A::bigTalk insteadof B;
|
|
B::bigTalk as talk;
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.traits.visibility">
|
|
<title>Changer la visibilité des méthodes</title>
|
|
<para>
|
|
En utilisant la syntaxe <literal>as</literal>, vous pouvez aussi ajuster
|
|
la visibilité de la méthode dans la classe qui l'utilise.
|
|
</para>
|
|
<example xml:id="language.oop5.traits.visibility.ex1">
|
|
<title>Changer la visibilité des méthodes</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait HelloWorld {
|
|
public function sayHello() {
|
|
echo 'Hello World!';
|
|
}
|
|
}
|
|
|
|
// Modification de la visibilité de la méthode sayHello
|
|
class MyClass1 {
|
|
use HelloWorld { sayHello as protected; }
|
|
}
|
|
|
|
// Utilisation d'un alias lors de la modification de la visibilité
|
|
// La visibilité de la méthode sayHello n'est pas modifiée
|
|
class MyClass2 {
|
|
use HelloWorld { sayHello as private myPrivateHello; }
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.traits.composition">
|
|
<title>Traits Composés depuis d'autres Traits</title>
|
|
<para>
|
|
Tout comme les classes peuvent utiliser des traits, d'autres traits le
|
|
peuvent aussi. Un trait peut donc utiliser d'autres traits et hériter
|
|
de tout ou d'une partie de ceux-ci.
|
|
</para>
|
|
<example xml:id="language.oop5.traits.composition.ex1">
|
|
<title>Traits Composés depuis d'autres Traits</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait Hello {
|
|
public function sayHello() {
|
|
echo 'Hello ';
|
|
}
|
|
}
|
|
|
|
trait World {
|
|
public function sayWorld() {
|
|
echo 'World!';
|
|
}
|
|
}
|
|
|
|
trait HelloWorld {
|
|
use Hello, World;
|
|
}
|
|
|
|
class MyHelloWorld {
|
|
use HelloWorld;
|
|
}
|
|
|
|
$o = new MyHelloWorld();
|
|
$o->sayHello();
|
|
$o->sayWorld();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Hello World!
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.traits.abstract">
|
|
<title>Méthodes abstraites dans les Traits</title>
|
|
<para>
|
|
Les traits supportent l'utilisation de méthodes abstraites afin d'imposer
|
|
des contraintes aux classes sous-jacentes. Les méthodes publiques, protégées,
|
|
et privées sont supportées.
|
|
Antérieur à PHP 8.0.0, seule les méthodes publiques et protégées abstraire
|
|
étaient supportées.
|
|
</para>
|
|
<caution>
|
|
<simpara>
|
|
Une classe concrète satisfait ces conditions en définissant une méthode concrète
|
|
avec le même nom ; sa signature peut être différente.
|
|
</simpara>
|
|
</caution>
|
|
<example xml:id="language.oop5.traits.abstract.ex1">
|
|
<title>Obligations requises par les méthodes abstraites</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait Hello {
|
|
public function sayHelloWorld() {
|
|
echo 'Hello'.$this->getWorld();
|
|
}
|
|
abstract public function getWorld();
|
|
}
|
|
|
|
class MyHelloWorld {
|
|
private $world;
|
|
use Hello;
|
|
public function getWorld() {
|
|
return $this->world;
|
|
}
|
|
public function setWorld($val) {
|
|
$this->world = $val;
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.traits.static">
|
|
<title>Attributs statiques dans les Traits</title>
|
|
<para>
|
|
Les traits peuvent définir des variables statiques, méthodes statiques
|
|
et propriétés statiques.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
À partir de PHP 8.1.0, appeler une méthode statique ou accéder à une
|
|
propriété statique directement sur un trait est obsolète.
|
|
Les méthodes et propriétés statiques devraient seulement être accédé sur une classe utilisant le trait.
|
|
</para>
|
|
</note>
|
|
<example xml:id="language.oop5.traits.static.ex1">
|
|
<title>Variables statiques</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait Counter {
|
|
public function inc() {
|
|
static $c = 0;
|
|
$c = $c + 1;
|
|
echo "$c\n";
|
|
}
|
|
}
|
|
|
|
class C1 {
|
|
use Counter;
|
|
}
|
|
|
|
class C2 {
|
|
use Counter;
|
|
}
|
|
|
|
$o = new C1(); $o->inc(); // echo 1
|
|
$p = new C2(); $p->inc(); // echo 1
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<example xml:id="language.oop5.traits.static.ex2">
|
|
<title>Méthodes statiques</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait StaticExample {
|
|
public static function doSomething() {
|
|
return 'Doing something';
|
|
}
|
|
}
|
|
|
|
class Example {
|
|
use StaticExample;
|
|
}
|
|
|
|
Example::doSomething();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<example xml:id="language.oop5.traits.static.ex3">
|
|
<title>Propriétés statiques</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait StaticExample {
|
|
public static $static = 'foo';
|
|
}
|
|
|
|
class Example {
|
|
use StaticExample;
|
|
}
|
|
|
|
echo Example::$static;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect2>
|
|
<sect2 xml:id="language.oop5.traits.properties">
|
|
<title>Propriétés</title>
|
|
<para>
|
|
Les traits peuvent aussi définir des propriétés.
|
|
</para>
|
|
<example xml:id="language.oop5.traits.properties.example">
|
|
<title>Définir des propriétés</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait PropertiesTrait {
|
|
public $x = 1;
|
|
}
|
|
|
|
class PropertiesExample {
|
|
use PropertiesTrait;
|
|
}
|
|
|
|
$example = new PropertiesExample;
|
|
$example->x;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Si un trait définit une propriété, alors la classe ne peut pas définir une
|
|
propriété de même nom sauf si elle est compatible (même visibilité et valeur
|
|
initiale), sinon une erreur fatale est émise.
|
|
</para>
|
|
<example xml:id="language.oop5.traits.properties.conflicts">
|
|
<title>Résolution des conflits</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
trait PropertiesTrait {
|
|
public $same = true;
|
|
public $different = false;
|
|
}
|
|
|
|
class PropertiesExample {
|
|
use PropertiesTrait;
|
|
public $same = true;
|
|
public $different = true; // Fatal error
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</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
|
|
-->
|