开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第二阶段:静态延迟绑定】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/712/detail/12696
静态迟延绑定
主要内容:
一、概念
二、步骤
三、示例
四、具体原理
一、概念
静态延迟绑定 static 关键字,是类内部用来代替类本身的关键字部分,不是在类本身编译也就是加载的时候就固定好的,而是调用的时候动态地选择来访者所属的类,这个就是静态延迟绑定,也可以理解为动态绑定。
它的核心是使用 static 关键字来代替 self,self 是属于静态绑定,如果需要用到静态延迟绑定,通常是因为需要使用到静态成员的重写,因为不重写就不存在动态的概念,如果在继承的类里面只有唯一的一个属性,那就不存在动态的问题,是固定的一个。
静态延迟绑定时为了明确访问的主体为类。
二、步骤
1.要访问的内容为静态成员(类成员、类常量也可以)
2.需要动态确定访问者而不是把它固定,这时候就可以使用静态延迟绑定。
三、示例
定义一个属性,这个属性名称叫 $name,名字就等于当前的类名,进行访问就可以使用 self 访问,这是确定的,第二个是用延迟绑定,此时这个 static 不代表human 类,谁来访问 static 代表谁,当 human 访问,那 static 就代表 human ,因此这两个都会输出 human。
代码如下:
#静态延迟访问
# 父类
class Human{
public static $name ='Human';
public static function showName(){
#静态绑定
echo self::$name,'
';# 静态延迟绑定
echo static::$name,'
';
Huran::showName();
# 输出 Human和Human (此时没子类的事儿)
来看一下这个代码,把类的代码运行一下,发现都输出了 human,说明 static 确实代表了当前的类名,但是此时并没有体现动态的效果,也没有体现出延迟的效果,因为看到的好像是一下,只是代替了 self 而已,一定要通过继承的子类来访问才有效果,而且这个时候最好要出现重写。
代码如下:
# 子类
class Man extends Human{
# 重写父类静态属性
public static Sname='Man';
#静态属性因为存储在类内部,因此不会覆盖
比如说有一个 man 类继承了一个 human 类,里面也有一个静态的属性,这就完成了重写,得到了一个新的值,就是 man 值,然后访问时对应要用 man 方法,因为man 继承了 Human 类,所以这个公有的方法也被继承了,那么使用的时候就可以调用这个方法,
这个时候自然时用 huamn 类去访问,代表的依然时不动的,因为这个时候和有没有这个子类是没有关系的,但如果现在用子类调用,第一个输出的还是 human,编译时,self 下面时 huamn¥name,static 下面是?¥name,?代表不确定,谁来访问就代表谁。如果此时 man 来访问,就代表 man,man 下面的类就是子类的name,结果看到的是 man,这就是延迟绑定。
关于谁的属性或者一些静态成员的时候,就可以使用 static 来做延迟绑定。
四、具体原理
当代码开始运行的时候就开始编译代码,编译代码的时候就要区分是静态绑定还是静态延迟绑定。
如果是静态绑定,就是 self,这是 self 就等于当前类名,不管有没有继承,而如果是静态延迟绑定,static 是等于位置类名,暂时不固定。而 self 在调用就明确了类名,访问的就是这个类里面的静态成员,而 static 看具体谁调用。
但是如果没有这个属性,这里走的又是 human,因为 static 没有这个属性的时候,虽然代表的是子类,但却是继承来的¥name 的属性,这个时候静态动态就没有区别。
最后做一个小结,静态延迟绑定时通过 static 关键字代替 self 进行类静态成员的内部访问,被访问时才觉得使用哪个类,与 self 不同,对比的时静态绑定,静态延迟绑定的意义时用来保证访问的静态成员是根据调用类的不同而选择不同的表现可以理解为一种多态的效果。