php-doc-en/language/oop5/late-static-bindings.xml
Daniel Egeberg 96c9d88bad Converted to utf-8
git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@297028 c90b9560-bf6c-de11-be94-00142212c4b1
2010-03-28 22:10:10 +00:00

272 lines
5.9 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<sect1 xml:id="language.oop5.late-static-bindings" xmlns="http://docbook.org/ns/docbook">
<title>Late Static Bindings</title>
<para>
As of PHP 5.3.0, PHP implements a feature called late static bindings which
can be used to reference the called class in a context of static inheritance.
</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.
It was also called a "static binding" as it can be used for (but is not
limited to) static method calls.
</para>
<sect2 xml:id="language.oop5.late-static-bindings.self">
<title>Limitations of <literal>self::</literal></title>
<para>
Static references to the current class like <literal>self::</literal> or
<literal>__CLASS__</literal> are resolved using the class in which the
function belongs, as in where it was defined:
</para>
<example>
<title><literal>self::</literal> usage</title>
<programlisting role="php">
<![CDATA[
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
A
]]>
</screen>
</example>
</sect2>
<sect2 xml:id="language.oop5.late-static-bindings.usage">
<title>Late Static Bindings' usage</title>
<para>
Late static bindings tries to solve that limitation by introducing a
keyword that references the class that was initially called at runtime.
Basically, a keyword that would allow you to reference
<literal>B</literal> from <literal>test()</literal> in the previous
example. It was decided not to introduce a new keyword but rather use
<literal>static</literal> that was already reserved.
</para>
<example>
<title><literal>static::</literal> simple usage</title>
<programlisting role="php">
<![CDATA[
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
B
]]>
</screen>
</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.
</para>
</note>
<example>
<title><literal>static::</literal> usage in a non-static context</title>
<programlisting role="php">
<![CDATA[
<?php
class TestChild extends TestParent {
public function __construct() {
static::who();
}
public function test() {
$o = new TestParent();
}
public static function who() {
echo __CLASS__."\n";
}
}
class TestParent {
public function __construct() {
static::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
$o = new TestChild;
$o->test();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
TestChild
TestParent
]]>
</screen>
</example>
<note>
<para>
Late static bindings' resolution will stop at a fully resolved static call
with no fallback. On the other hand, static calls using keywords like
<literal>parent::</literal> or <literal>self::</literal> will forward the
calling information.
</para>
<example>
<title>Forwarding and non-forwarding calls</title>
<programlisting role="php">
<![CDATA[
<?php
class A {
public static function foo() {
static::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
class B extends A {
public static function test() {
A::foo();
parent::foo();
self::foo();
}
public static function who() {
echo __CLASS__."\n";
}
}
class C extends B {
public static function who() {
echo __CLASS__."\n";
}
}
C::test();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
A
C
C
]]>
</screen>
</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:
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
-->