- More precise description on how LSB works.

- Differences between $this-> and static:: in non-static contexts.
- Removed vague "edge cases" section, with an example that was not really surprising.

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@303545 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
Gustavo André dos Santos Lopes 2010-09-19 06:58:29 +00:00
parent 225e956391
commit b579b724d1

View file

@ -7,11 +7,27 @@
can be used to reference the called class in a context of static inheritance.
</para>
<para>
More precisely, late static bindings work by storing the class named in the
last "non-forwarding call". In case of static method calls, this is the
class explicitly named (usually the one on the left of the
<link linkend="language.oop5.paamayim-nekudotayim"><literal>::</literal></link>
operator); in case of non static method calls, it is the class of the object. A
"forwarding call" is static one that is introduced by <literal>self::</literal>,
<literal>parent::</literal>, <literal>static::</literal>, or, if going
up in the class hierarchy, <function>forward_static_call</function>.
<!-- technically, static:: may be non forwarding, but it's irrelevant -->
The function <function>get_called_class</function> can be used to retrieve
a string with the name of the called class and <literal>static::</literal>
introduces its scope.
</para>
<para>
This feature was named "late static bindings" with an internal perspective in
mind. "Late binding" comes from the fact that <literal>static::</literal>
will no longer be resolved using the class where the method is defined but
it will rather be computed using runtime information.
will not be resolved using the class where the method is defined but it will
rather be computed using runtime information.
It was also called a "static binding" as it can be used for (but is not
limited to) static method calls.
@ -103,10 +119,11 @@ B
</example>
<note>
<para>
<literal>static::</literal> does not work like <literal>$this</literal> for
static methods! <literal>$this-></literal> follows the rules of
inheritance while <literal>static::</literal> doesn't. This difference is
detailed later on this manual page.
Note that, in non-static contexts, the called class will be the same as
the class the object. Since <literal>$this-></literal> will try to call
private methods from the same scope, using <literal>static::</literal> may
give different results. Another difference is that
<literal>static::</literal> can only refer to static properties.
</para>
</note>
<example>
@ -114,40 +131,43 @@ B
<programlisting role="php">
<![CDATA[
<?php
class TestChild extends TestParent {
public function __construct() {
static::who();
class A {
private function foo() {
echo "success!\n";
}
public function test() {
$o = new TestParent();
}
public static function who() {
echo __CLASS__."\n";
$this->foo();
static::foo();
}
}
class TestParent {
public function __construct() {
static::who();
}
class B extends A {
/* foo() will be copied to B, hence its scope will still be A and
* the call be successful */
}
public static function who() {
echo __CLASS__."\n";
class C extends A {
private function foo() {
/* original method is replaced; the scope of the new one is C */
}
}
$o = new TestChild;
$o->test();
$b = new B();
$b->test();
$c = new C();
$c->test(); //fails
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
TestChild
TestParent
success!
success!
success!
Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9
]]>
</screen>
</example>
@ -205,50 +225,6 @@ C
</example>
</note>
</sect2>
<sect2 xml:id="language.oop5.late-static-bindings.edge-cases">
<title>Edge cases</title>
<para>
There are lots of different ways to trigger a method call in PHP, like
callbacks or magic methods. As late static bindings base their resolution
on runtime information, it might give unexpected results in so-called edge
cases.
</para>
<example>
<title>Late static bindings inside magic methods</title>
<programlisting role="php">
<![CDATA[
<?php
class A {
protected static function who() {
echo __CLASS__."\n";
}
public function __get($var) {
return static::who();
}
}
class B extends A {
protected static function who() {
echo __CLASS__."\n";
}
}
$b = new B;
$b->foo;
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
B
]]>
</screen>
</example>
</sect2>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
@ -270,3 +246,4 @@ vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->