static 、self 、 parent

来源:互联网 发布:七天网络查询成绩登陆 编辑:程序博客网 时间:2024/05/20 11:32

PHP中static 、self 、 parent的指向很让人迷惑,趁有时间,把学习结果记录一下。

static

static 关键字来定义静态方法和属性。
static 也可用于定义静态变量以及后期静态绑定。

static 关键字来定义静态方法和属性。

声明类属性或方法为静态,就可以不实例化类而直接访问。

静态属性和方法可以通过以下方法访问:
类名::静态属性/方法
对象::静态属性/方法
selft::静态属性/方法
static::静态属性/方法
parent::静态属性/方法
之所以要写这个文章来记录下static 、self 、 parent的区别,就是因为调用方法有这么多种。这里涉及PHP里面 后期静态绑定 的概念。

static 用于定义静态变量

静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失。
静态变量如果定义为全局的function,则作用域贯穿某次完整的请求。
静态变量如果定义为类的function,则作用域为该类实例化后的作用域,对象销毁了就丢失了。
静态变量如果定义为类的静态方法的静态变量,那作用域就跟全局function里的作用域一样了。

后期静态绑定

自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。
理解后期静态绑定其实是件非常困难的事,php官方文档解释得也非常绕,所以要认真理解。试想面向对象编程中,类是有继承关系的,静态方法或属性也会被继承或者覆盖,如果直接继承没有任何覆盖,那最终调用都将会是父类的静态方法或属性,这样不会冲突。但是,如果静态方法或属性被覆盖了,怎么处理覆盖关系呢?

PHP引入”后期静态绑定” 来解决冲突,原理上就是用一个变量记录发起调用的类是”谁“,这个变量是static变量,实质上static变量是个多职责的变量,在“转发调用”的场景下,static跟self没有区别,在“非转发调用”的场景下,static永远代表发起调用的类。具体什么叫“转发调用”和“非转发调用”待会再解释,这里知道static有两个职责就可以。

接着看冲突是怎么被解决的。如下代码,将会打印“A”,因为self永远指向类定义本身,发起者B会被static变量记录下来,如果把 self::who(); 修改为 static::who();就会打印出“B”。这种以类B作为出发点发起调用的方式也叫做“非转发调用”, 同时,如果把B实例化之后变成b,b::test();这样调用的话,也叫做“非转发调用”。其实我也还没弄清楚为啥叫“非转发调用”,而“后期静态绑定”就可以理解为static的指向是不固定的,会因为子类的继承关系而变化,所以static的值是运行过程中才绑定的。由此看来,静态方法或者属性被继承之后又发生覆盖的话,需要非常自己处理调用关系,不然就会产生人称“神器的BUG”。

<?phpclass A {    public static function who() {        echo __CLASS__;    }    public static function test() {        self::who(); // static::who()    }}class B extends A {    public static function who() {        echo __CLASS__;    }}B::test();?>

相对于static来说,self和parent的指向是固定的,self执行的就是类定义本身,parent就是当前的类的直接父类,使用self引用静态方法或属性时,指向的就是类定义自己,如果类本身没有定义,则直接继承父类的定义,父类没有定义,则继承父类的父类的定义,不管实际调用的类是谁。

0 0
原创粉丝点击