最近在看PHP手册,看到类和对象的时候,有一个“后期静态绑定”的内容,self,static,parent这几个关键字弄的我云里雾里,索性查了一些资料,看看self,final,static,this,parent这些关键字到底是什么意思。
自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。
准确说,后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类。所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,static:: 则指出了其范围。
该功能从语言内部角度考虑被命名为“后期静态绑定”。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。
因为存在继承和不存在继承的情况下,self,static,parent关键字的作用不同,而this和final是不受继承限制的,我们先来看看this,final。
关键字this
1 | class name //建立了一个名为name的类 |
Note:上面的类分别在语句(1)和语句(2)使用了 this 指针,那么当时 this 是指向谁呢?其实 this 是在实例化的时候来确定指向谁,比如第一次实例化对象的时候(语句(3)),那么当时 this 就是指向 \$obj1 对象,那么执行语句(2)的打印时就把
1 | print($this->name) |
变成了
1 | print($obj1->name) |
那么当然就输出了”PHP_Home”。
第二个实例的时候,
1 | print($this->name ) |
变成了
1 | print( $obj2->name) |
于是就输出了”PHP”。所以说,this 是指向当前对象实例的指针,不指向任何其他对象或类。
关键字final
如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。
final 方法示例:
1 | class BaseClass { |
final 类示例:
1 | final class BaseClass { |
Note:属性不能被定义为 final,只有类和方法才能被定义为 final。
下面我们在存在继承和不存在继承两种情况下看看self,static,parent关键字的作用。
不存在继承的时候
顾名思义,不存在继承就是书写一个单独的类来使用。self 和 static 在范围解析操作符 (::) 的使用上,并无区别。
在静态函数中,self 和 static 可以调用静态属性和静态函数(没有实例化类,因此不能调用非静态的属性和函数)。
在非静态函数中,self 和 static 可以调用静态属性和静态函数以及非静态函数。
不存在继承的情况下,self 和 static 的作用是一样的,同时可替换为 类名:: 的方式调用。
1 | class Demo { |
输出结果为:
1 | static |
存在继承的时候
示例1:
1 | class A { |
输出结果为:
1 | this is class A |
Note:self 调用的静态方法或属性始终表示其在使用的时候的当前类(A)的方法或属性,可以替换为其类名,static 调用的静态方法或属性会在继承中被其子类重写覆盖,应该替换为对应的子类名(B)。
对于parent关键字,用于调用父类的方法和属性。在静态方法中,可以调用父类的静态方法和属性;在非静态方法中,可以调用父类的方法和属性。
1 | class A { |
输出结果为:
1 | static |
PHP手册中的例子
1 | class A { |
输出结果为:
1 | A |
我们分析 test() 方法:
1 | public static function test() { |
A::foo();这个语句是可以在任何地方执行的,它表示使用A去调用静态方法 foo() 得到“A”。
parent::foo();C 的 parent 是 B , B 的parent是A,回溯找到了A 的 foo 方法;static::who();语句中的 static:: 调用的方法会被子类覆盖,所以优先调用 C 的 who() 方法,如果 C 的 who 方法不存在会调用 B 的 who 方法,如果 B 的 who 方法不存在会调用 A 的 who 方法。所以,输出结果是”C”。
self::foo();这个 self:: 是在 B 中使用的,所以 self:: 等价于 B:: ,但是 B 没有实现 foo() 方法,B 又继承自 A,所以我们实际上调用了 A::foo() 这个方法。foo() 方法使用了static::who() 语句,导致我们又调用了 C 的 who 函数。
Read More:
PHP中this,self,parent的区别 Final 关键字 后期静态绑定 PHP中的self、static、parent关键字