Files
doc-fr/language/oop5/late-static-bindings.xml
T
George Peter Banyard 66e0862a74 Apply commit 9ee9eccf455188ab6eb352194eb6f9eb99e15606
Refactor OO section part 2
2021-03-17 14:52:17 +00:00

256 lines
6.8 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 9ee9eccf455188ab6eb352194eb6f9eb99e15606 Maintainer: jpauli Status: ready -->
<!-- Reviewed: no -->
<sect1 xml:id="language.oop5.late-static-bindings" xmlns="http://docbook.org/ns/docbook">
<title>Late Static Bindings (Résolution statique à la volée)</title>
<para>
PHP implémente une fonctionnalité appelée
<literal>late static binding</literal>, en français la résolution
statique à la volée, qui peut être utilisée pour référencer la classe appelée
dans un contexte d'héritage statique.
</para>
<para>
Plus précisément, les résolutions statiques à la volée fonctionnent en enregistrant
le nom de la classe dans le dernier "appel non transmis". Dans le cas des appels de
méthodes statiques, il s'agit de la classe explicitement nommée (généralement, celle à
gauche de l'opérateur
<link linkend="language.oop5.paamayim-nekudotayim"><literal>::</literal></link>) ;
dans le cas de méthodes non statiques, il s'agit de la classe de l'objet. Un "appel
transmis" est un appel statique déclenché par <literal>self::</literal>,
<literal>parent::</literal>, <literal>static::</literal>, ou, tout en haut de la
hiérarchie des classes, <function>forward_static_call</function>.
<!-- technically, static:: may be non forwarding, but it's irrelevant -->
La fonction <function>get_called_class</function> peut être utilisée pour récupérer
une chaine contenant le nom de la classe appelée, et <literal>static::</literal>
introduit son espace.
</para>
<para>
Cette fonctionnalité a été baptisée <literal>"late static bindings"</literal>,
avec un point de vue interne. <literal>"Late binding"</literal>, littéralement
résolution tardive, vient du fait que les éléments <literal>static::</literal>
ne seront pas résolus en utilisant la classe où la méthode a été définie, mais
celle qui est active durant l'exécution. L'adjectif statique a été
ajouté car ce problème s'applique (sans y être limité) aux méthodes statiques.
</para>
<sect2 xml:id="language.oop5.late-static-bindings.self">
<title>Limitations de <literal>self::</literal></title>
<para>
Les références statiques à la classe courante, avec <literal>self::</literal> ou
<literal>__CLASS__</literal>, sont résolues en utilisant la classe à laquelle
appartiennent les fonctions, celle où elles ont été définies :
</para>
<example>
<title>Utilisation de <literal>self::</literal></title>
<programlisting role="php">
<![CDATA[
<?php
class A {
public static function qui() {
echo __CLASS__;
}
public static function test() {
self::qui();
}
}
class B extends A {
public static function qui() {
echo __CLASS__;
}
}
B::test();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
A
]]>
</screen>
</example>
</sect2>
<sect2 xml:id="language.oop5.late-static-bindings.usage">
<title>Utilisation de la résolution statique à la volée</title>
<para>
La résolution statique à la volée essaie de dépasser cette limitation
en introduisant un mot clé qui fait référence à la classe
qui a été appelée durant l'exécution. Pour faire simple, ce mot-clé
permet le référencement à <literal>B</literal> depuis
<literal>test()</literal>, dans l'exemple précédent.
Il a été décidé de ne pas introduire de nouveau mot clé, mais
plutôt d'utiliser le mot <literal>static</literal> qui était déjà
réservé.
</para>
<example>
<title>Utilisation simple de <literal>static::</literal></title>
<programlisting role="php">
<![CDATA[
<?php
class A {
public static function qui() {
echo __CLASS__;
}
public static function test() {
static::qui(); // Ici, résolution à la volée
}
}
class B extends A {
public static function qui() {
echo __CLASS__;
}
}
B::test();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
B
]]>
</screen>
</example>
<note>
<para>
Dans les contextes non statiques, la classe appelée sera celle de l'objet.
Comme <literal>$this-></literal> essayera d'appeler
des méthodes privées depuis le même contexte, utiliser <literal>static::</literal>
pourrait donner des résultats différents. Notez aussi que
<literal>static::</literal> ne peut faire référence qu'à des attributs/méthodes
statiques.
</para>
</note>
<example>
<title>Utilisation de <literal>static::</literal> dans un contexte non statique</title>
<programlisting role="php">
<![CDATA[
<?php
class A {
private function foo() {
echo "success!\n";
}
public function test() {
$this->foo();
static::foo();
}
}
class B extends A {
/* foo() sera copiée dans B, par conséquent son contexte sera toujours A
* et l'appel se fera sans problème */
}
class C extends A {
private function foo() {
/* La méthode originale est remplacée; le contexte est celui de C */
}
}
$b = new B();
$b->test();
$c = new C();
$c->test(); //échoue
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
success!
success!
success!
Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9
]]>
</screen>
</example>
<note>
<para>
La résolution des statiques à la volée va s'arrêter à un appel statique
complètement résolu. D'un autre coté, les appels statiques en utilisant
un mot-clé comme <literal>parent::</literal> ou <literal>self::</literal>
vont transmettre l'information appelante.
</para>
<example>
<title>Appel avec ou sans transmission</title>
<programlisting role="php">
<![CDATA[
<?php
class A {
public static function foo() {
static::qui();
}
public static function qui() {
echo __CLASS__."\n";
}
}
class B extends A {
public static function test() {
A::foo();
parent::foo();
self::foo();
}
public static function qui() {
echo __CLASS__."\n";
}
}
class C extends B {
public static function qui() {
echo __CLASS__."\n";
}
}
C::test();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
A
C
C
]]>
</screen>
</example>
</note>
</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
-->