共计 1835 个字符,预计需要花费 5 分钟才能阅读完成。
后缀
后期静态绑定也就是 static::
在类中的用法,首先需要明确一点,static::
后可跟 类常量 、 静态属性(类变量)、静态方法 和 普通方法 (跟 类常量 / 静态属性 / 静态方法 时 static
代表一个类,跟 普通方法时 static
代表一个对象), 不可以跟普通属性(对象的成员变量),因为语义上无法辨别是普通属性还是静态属性(语法都是 static::$xx)。
引入目的
引入后期静态绑定的目的是为了打破 self::
关键词的限制,类中 self
的指向在编译时期便确定在了代码上下文中 self
所在的类。而 static::
则是在运行时确定其指向。在继承关系中,便可看出 self
和 static
的区别。
使用场景
static:: 跟类常量的场景
class A {
public const FOO = 'a';
public function test() {echo self::FOO; // self 明确指向代码上下文中所在类 A,即使被子类调用,self 也是指向 A}
}
class B extends A {public const FOO = 'b';}
(new B)->test(); // 输出 a
class A {
public const FOO = 'a';
public function test() {echo static::FOO; // static 在编译阶段不确定指向,运行时才确定指向,指向调用者,故称为 ` 后期绑定 `。此处 static 后跟类常量,故 static 代表调用类,也就是 B 类。}
}
class B extends A {public const FOO = 'b';}
(new B)->test(); // 输出 b
static:: 跟静态属性的场景(同理)
class A {
public static $foo = 'a';
public static function test() {echo self::$foo;}
}
class B extends A {public static $foo = 'b';}
B::test(); // 输出 a
class A {
public static $foo = 'a';
public static function test() {echo static::$foo;}
}
class B extends A {public static $foo = 'b';}
B::test(); // 输出 b
static:: 跟静态方法的场景
class A {public static function who() {echo __CLASS__; // __CLASS__ 编译时期绑定了 A 类名}
public static function test() {self::who(); // self 在编译时期就指向了 A 类
}
}
class B extends A {public static function who() {echo __CLASS__; // __CLASS__ 编译时期绑定了 B 类名}
}
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
static:: 跟普通方法的场景
除了代替 self::
,static::
在一些场景中也可代替 $this->
。
有种场景是这样的:当父类中的方法被子类调用时,方法中的 $this-> 会首先在其所在范围(代码上下文,即父类)里寻找私有方法或属性,如果寻找不到才会调用其子类的方法或属性。而 static 属于后期绑定,可绕过这一步,直接指向方法的调用者。
class A {private function foo() {echo "a\n";}
public function test() {$this->foo(); // 所在范围中存在私有方法 foo,所以并不会调用 B 中的 foo 方法
}
}
class B extends A {public function foo() {echo "b\n";}
}
(new B)->test(); // 输出 a
class A {private function foo() {echo "a\n";}
public function test() {static::foo(); // 绕过检查,直接调用调用者的该方法
}
}
class B extends A {public function foo() {echo "b\n";}
}
(new B)->test(); // 输出 b
正文完