后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类。所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,static::则指出了其范围。
在无继承的时候,self::和static::的用法一样,parent::也就自然用不上.
当存在继承的时候,self::指当前所在的类,static::指被调用方法或者属性所在的类
使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类
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();
结果为:A
class A { public static function who() { echo __CLASS__; } public static function test() { static::who(); // 后期静态绑定从这里开始 } } class B extends A { public static function who() { echo __CLASS__; } } B::test();
结果为:B
class A{ public function test(){ echo "A"; } } class B extends A{ public function test(){ echo "B"; } public function foo(){ parent::test(); } } $obj = new B(); $obj->foo();
结果为:A
综合案例:
class A{ public $name = "a"; public static $age = 10; public static $hobby ="football"; public function __construct(){ echo __CLASS__,'<br/>'; } public function index(){ echo "index的class:".__CLASS__."<br/>"; echo "index的name属性:".$this->name."<br />"; echo "index的hobby属性:".static::$hobby."<br />"; echo "年龄为",self::$age,"<br>"; } } class B extends A{ public $name = "b"; public static $age = 20; public static $hobby ="Basketball"; public function index(){ parent::index(); echo "index的class:".__CLASS__."<br/>"; echo "index的name属性:".$this->name."<br />"; echo "index的hobby属性:".static::$hobby."<br />"; echo "年龄为",self::$age,"<br>"; } } class C extends B{ public $name = "c"; public static $age = 30; public static $hobby ="Swimming"; public function __construct(){ parent::__construct(); echo __CLASS__,'<br/>'; } } $obj = new C(); $obj->index();
结果为:(一共运行2次index)
A C index的class:A index的name属性:c index的hobby属性:Swimming 年龄为10 index的class:B index的name属性:c index的hobby属性:Swimming 年龄为20
在C类中重载class方法,结果会不同
class A{ public $name = "a"; public static $age = 10; public static $hobby ="football"; public function __construct(){ echo __CLASS__,'<br/>'; } public function index(){ echo "index的class:".__CLASS__."<br/>"; echo "index的name属性:".$this->name."<br />"; echo "index的hobby属性:".static::$hobby."<br />"; echo "年龄为",self::$age,"<br>"; } } class B extends A{ public $name = "b"; public static $age = 20; public static $hobby ="Basketball"; public function index(){ parent::index(); echo "index的class:".__CLASS__."<br/>"; echo "index的name属性:".$this->name."<br />"; echo "index的hobby属性:".static::$hobby."<br />"; echo "年龄为",self::$age,"<br>"; } } class C extends B{ public $name = "c"; public static $age = 30; public static $hobby ="Swimming"; public function __construct(){ parent::__construct(); echo __CLASS__,'<br/>'; } public function index(){ parent::index(); echo "index的class:".__CLASS__."<br/>"; echo "index的name属性:".$this->name."<br />"; echo "index的hobby属性:".static::$hobby."<br />"; echo "年龄为",self::$age,"<br>"; } } $obj = new C(); $obj->index();
结果:(一共运行3次index)
A C index的class:A index的name属性:c index的hobby属性:Swimming 年龄为10 index的class:B index的name属性:c index的hobby属性:Swimming 年龄为20 index的class:C index的name属性:c index的hobby属性:Swimming 年龄为30总结:C中没有index方法,继承了B的方法,而调用的时候是直接运行B里面的,而B中parent::index()会运行A中的index(),但是里面的变量或者方法还是C的,除非是self,__CLASS__等表示当前类的.