php方法调用中self,this,static的区别

3,436 阅读3分钟

最近深入了解了一下self,this,static在PHP方法调用时的区别,现根据自己的了解做出一些总结,不对的地方还请指正

分别代表的意义

self :转发调用的一种。使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类,如下:

所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,static:: 则指出了其范围

<?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();
?>

以上例程会输出:A

原因: B调用的test方法为A类所定义,故self指向其定义所在类,即A

如下:

<?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__;
    }
    public static function test() {
        self::who();
    }
}

B::test();

此时会输出B;

static :转发调用的一种。用于后期静态绑定,也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。

自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。 当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类 ------摘自php.net

后期静态绑定本想通过引入一个新的关键字表示运行时最初调用的类来绕过限制。简单地说,这个关键字能够让你在上述例子中调用 test() 时引用的类是 B 而不是 A。最终决定不引入新的关键字,而是使用已经预留的 static 关键字。 ------摘自php.net

static::的用法:

<?php
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;

原因: static将其指向了运行时最初调用的类,也就是B

但是,下面一种情况:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // 后期静态绑定从这里开始
    }
}

class B extends A {

}
?>

B::test();

此时会输出A;

因为B类中没有who方法,所以不得不又调用A类中的who方法。

Note: 在非静态环境下,所调用的类即为该对象实例所属的类。由于 $this-> 会在同一作用范围内尝试调用私有方法,而 static:: 则可能给出不同结果。另一个区别是 static:: 只能用于静态属性。

如下:

<?php
class A {
    private function foo() {
        echo "success!\n";
    }
    public function test() {
        $this->foo();
        static::foo();
    }
}

class B extends A {
   /* foo() will be copied to B, hence its scope will still be A and
    * the call be successful */
}

class C extends A {
    private function foo() {
        /* original method is replaced; the scope of the new one is C */
    }
}

$b = new B();
$b->test();
$c = new C();
$c->test();   //fails
?>

以上例程将会输出:

success!
 success!
 success!

 Fatal error:  Call to private method C::foo() from context 'A' in /tmp/test.php on line 9

原因: 在C类中重写了A类中的私有方法,在test方法中执行static::foo()时,由于static指向的是C类,而当前的作用范围是在A类中,所以会在A类中调用C类中的私有方法,显然是错误的。

$this :指向当前类对象的实例,也就是对当前实例的一个引用。在静态方法中不能使用$this关键字,因为静态方法是属于类的,可供类直接调用,而其在调用时可能并没有创建对象,故此。

如下:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        $this->who(); // 后期静态绑定从这里开始
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}
$b = new B();
$b->test();
?>

以上例程会输出:

PHP Fatal error:  Using $this when not in object context in php shell code on line 6

结语

$this在PHP中是相当强大的存在,在此不做详解,static,self的区别我想到现在为止大家应该
也有一定的了解了,如果有什么不够清晰或者疑问的地方,欢迎批评指正,大家共同探讨!