php 关于 self 和 static

实例

self:: 的限制

使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类:

self:: 用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

class {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}

class B extends {
public static function who() {
echo __CLASS__;
}
}

B::test();



A

后期静态绑定的用法

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

static:: 简单用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

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

class B extends {
public static function who() {
echo __CLASS__;
}
}

B::test();



B

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

非静态环境下使用 static::

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

class {
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

后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面,如果静态调用使用 parent:: 或者 self:: 将转发调用信息。

转发和非转发调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

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


A
C
C

总结

  • self__CLASS__,都是对当前类的静态引用,取决于定义当前方法所在的类。也就是说,self 写在哪个类里面, 它引用的就是谁。
  • $this 指向的是实际调用时的对象,也就是说,实际运行过程中,谁调用了类的属性或方法,$this 指向的就是哪个对象。但 $this 不能访问类的静态属性和常量,且 $this 不能存在于静态方法中。
  • static 关键字除了可以声明类的静态成员(属性和方法)外,还有一个非常重要的作用就是后期静态绑定。
  • self 可以用于访问类的静态属性、静态方法和常量,但 self 指向的是当前定义所在的类,这是 self 的限制。
  • $this 指向的对象所属的类和 static 指向的类相同。
  • static 可以用于静态或非静态方法中,也可以访问类的静态属性、静态方法、常量和非静态方法,但不能访问非静态属性。
  • 静态调用时,static 指向的是实际调用时的类;非静态调用时,static 指向的是实际调用时的对象所属的类

相关文章

https://www.php.net/manual/zh/language.oop5.late-static-bindings.php
https://blog.csdn.net/lamp_yang_3533/article/details/79912453