mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-16 00:48:54 +00:00
- 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:
parent
225e956391
commit
b579b724d1
1 changed files with 46 additions and 69 deletions
|
@ -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
|
||||
-->
|
||||
|
||||
|
|
Loading…
Reference in a new issue