PHP this parent static self 关键字

367 阅读2分钟

这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战

this

当一个对象要访问其方法时,会先完成一个绑定:将 $this 绑定到调用该方法的 对象。方法谁调用,$this 就指向谁。

self

self 永远指向 定义它的类。也就是你在哪里写了 self,self 就代表哪个类。

$this 绑定的是调用方法的对象,是对象级别,self 则是绑定的定义它的类,是类级别。因此只能用于访问静态方法或静态属性或常量。

parent

跟 self 类似,parent 指向的是定义它的 类的父类。也是类级别。

class AA
{
    public $name = 'AA <br/>';
 
    public static $age = 'AA 12 <br/>';
}
 
class BB extends AA
{
    public $name = 'BB <br/>';
 
    public static $age = 'BB 12 <br/>';
 
    public function foo()
    {
        echo self::$age;//BB 12 
 
        echo parent::$age;//AA 12 
 
        echo parent::$name;//Fatal error: Access to undeclared static property: AA::$name
 
        //echo parent->$name;//Parse error
    }
 
}
 
$bb = new BB();
$bb->foo();

static

static 关键字是 PHP 5.3 时引入的,官方名称是延迟静态绑定(late-static-bindings)。static 关键字可以在父类中引用到扩展类的最终状态,也就是指向 调用它的类。换句话,当碰到 static 关键字时,static 就指向了当前的调用域(calling scope),而不是像 self 等静态引用会寻找定义他们的域。

class AA
{
    public static $age = 'AA 12 <br/>';
 
    public function foo()
    {
        echo self::$age;//AA 12 
        echo static::$age;//BB 12
        static::bar();//BB bar(
        static::bar1();//BB bar1()
 
    }
}
 
class BB extends AA
{
    public static $age = 'BB 12 <br/>';
 
    public static function bar()
    {
        echo 'BB bar() <br/>';
    }
 
    public function bar1()
    {
        echo 'BB bar1() <br/>';
    }
}
 
$bb = new BB();
$bb->foo();

可以看到,static 关键字绑定了调用方法的类,而不是定义方法的类。一来来说,static 用于调用调用类的静态方法但不限于静态方法,例子中 BB 中的bar1() 就是非静态的,一样可以正常运行,不像 self、parent 一样会出错,但毕竟是类级别的绑定,还是必须使用 :: 而不能使用 ->。

手册上有这么一句话:后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面,如果静态调用使用 parent:: 或者 self:: 将转发调用信息。附加的例子也被面试者经常拿来考人。

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();//A调用A自己的foo(),static指向调用者当然为A
 
        parent::foo();//parent指的是当前类的父类A,调用者依然是C,
            //parent只是起到了“转发调用者”的作用。
            //A中的foo内的static解析到C,最后运行的是C的who(),输出的是__CLASS__为C
 
        self::foo();//同样的转发调用者,是C要调用B中的foo(),
            //千万不要理解为是B要调用B自己的foo()。这样理解的话结果就是B了。
    }
 
    public static function who() {
        echo __CLASS__."\n";
    }
}
 
class C extends B {
    public static function who() {
        echo __CLASS__."\n";
    }
}
 
C::test();//test()来自B。结果为A C C

手册上在非静态环境下使用static的例子引还引起了我的注意,不是不理解 static,而是对 $this 的行为让人诧异。

class A
{
    private function foo()
    {
        echo 'A foo()<br/>';
    }
 
    public function test()
    {
        $this->foo();//如果当前类中有foo且为private,会被运行。否则运行子类的
    }
}
 
class C extends A
{
    public function foo()
    {
        echo 'C foo()<br/>';
    }
}
 
$c = new C();
$c->test();//A中的foo()为private,运行A的。否则运行C的

$this-> will try to call private methods from the same scope