可继承性是面向对象编程的重要特征。在开发过程中,由于类与类之间继承关系,我们很容易弄混对象属性的真实归属,到底自己代码所调用的是父类属性还是子类属性呢?这里针对PHP语言,讨论一下
$this
、self
和parent
这三个关键字的作用。
基本概念
声明一下,以下的所有描述都是基于PHP的
E_STRICT
模式,也希望大家的PHP
代码运行于E_STRICT
模式下,否则代码很容易产生二义。
首先,$this
、self
和parent
只能在类定义内部使用。
$this
是一个伪变量,不能也不需要手动赋值。在类内部定义方法时,$this
自动指向了主叫对象,即是主叫对象的引用。如果没有实例化对象,$this
就是空值;在静态方法中$this
一直是空值,不管是被类名调用,还是被实例化对象调用。
与$this
不同,self
不是一个变量,不能作为参数传递予函数。在类定义内部,self
指向了当前的类。无关有没有实例化对象,self
是当前类的引用。在代码上,使用self
的地方,都可以用当前类名代替,且运行结果不会改变;然而,使用$this->
的地方,如果是在调用类方法(不是类属性),也可以用self::
代替,虽然语法上没有错误,但是逻辑上会有差异,详见下面 $this与self。
parent
也不是一个变量,也不能作为参数传递予函数。在类定义内部,parent
指向了当前类的直接父类,如果当前类没有父类,使用parent
则会报错。
$this与self
对于$this
与self
,一般认为:$this
引用类的实例化对象,可以调用类的所有属性和方法;而self
引用类本身,与实例化对象无关,只能调用静态资源(如类常量、静态属性和静态方法)。
但是实际上self
可以“踩过界”——self
也可以调用非静态资源。
分析
在类定义内部, $this->
后面可以连接当前类的所以类属性和类方法,但不能连接类常量;而self::
后面可以连接类常量、静态属性和 _所有类方法_。self
可以调用非静态方法,实际上是要借用当前类的实例化对象来调用的。
在静态方法中,self
不能调用非静态方法,正如$this
不能被使用;而在非静态方法中,self
就可以调用其他非静态方法了,正如$this
可以正常被使用。那么,在非静态方法中调用其他非静态方法,使用$this->
和使用self::
有什么区别呢?
1 |
|
对于调用非静态方法,可以这样来总结$this
和self
的区别:$this
是直接指向 运行时 的实例化对象的,而self
是借用 定义时 的实例化对象。(self
是不能调用非静态属性的,所以这一点不需要讨论$this
与self
的区别)
使用
假设父类定义了一个非静态方法a
,里面调用了另一个非静态方法b
:
- 如果希望子类的实例化对象调用
a
时可以使用子类自身的b
,那么,父类的a
定义时应该使用$this->b();
; - 如果希望子类的实例化对象调用
a
时可以使用父类的b
,那么,父类的a
定义时就应该使用self::b();
。
$this与parent
在类定义内部,parent
指向了当前类的直接父类。parent
和self
的意义不同,但是性质上是几乎一样的。
分析
parent::
后面可以连接直接父类的常量、静态属性和 _所有类方法_。parent
可以调用非静态方法,实际上是借用直接父类的实例化对象来调用的。
直接看代码:
1 |
|
对于调用非静态方法,parent
是借用 定义时 的直接父类的实例化对象。(parent
也是不能调用非静态属性的)
使用
后期静态绑定
性质上,self
和parent
可以归为一类,其实它们还有一个同类——static
。范围解析操作符::
,除了类名,就只有这三个关键字可以使用。
分析
上面 $this与self 的讨论是基于对非静态方法的调用,如果是对静态方法的调用呢?还是直接看代码:
1 |
|
这里static::
的作用,叫做 后期静态绑定,用于在继承范围内引用静态调用的类。从语言内部角度看,“后期绑定”的意思是说:static::
不被解析为 定义时 当前类,而是在实际 运行时 的使用类。static::
后面只能连接静态属性和静态方法,弥补了$this
与self
的不足。
使用
假设父类定义了一个静态方法a
,里面调用了另一个静态方法b
:
- 如果希望子类调用
a
时可以使用子类自身的b
,那么,父类的a
定义时应该使用static::b();
; - 如果希望子类调用
a
时可以使用父类的b
,那么,父类的a
定义时就应该使用self::b();
。
最后
所以在定义类的时候,应该使用$this
的地方就使用$this
,应该使用self
的地方就使用self
,parent
估计会很少用到,总之不要混着用了。