static 、self 、 parent

本文详细解析PHP中的static关键字,包括其定义静态方法和属性的作用、静态变量的特点、后期静态绑定的概念及其工作原理,并通过示例代码说明static、self与parent在类继承中的不同表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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”。

<?php
class 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引用静态方法或属性时,指向的就是类定义自己,如果类本身没有定义,则直接继承父类的定义,父类没有定义,则继承父类的父类的定义,不管实际调用的类是谁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值