详解PHP的self关键字

PHP群里有人询问self关键字的用法,答案是比较明显的:

静态成员函数内不能用this调用非成员函数,但可以用self调用静态成员函数/变量/常量;

其他成员函数可以用self调用静态成员函数以及非静态成员函数。

随着讨论的深入,发现self并没有那么简单。鉴于此,本文先对几个关键字做对比和区分,再总结self的用法。

与parent、static以及this的区别

要想将彻底搞懂self,要与parent、static、this区分开。

以下分别做对比

parent

self与parent的区分比较容易:parent引用父类/基类被隐盖的方法(或变量),self则引用自身方法(或变量)。

例如构造函数中调用父类构造函数:

`class` `Base {`

`public` `function` `__construct() {`

`echo` `"Base contructor!"``, PHP_EOL;`

`}`

`}`

`class` `Child {`

`public` `function` `__construct() {`

`parent::__construct();`

`echo` `"Child contructor!"``, PHP_EOL;`

`}`

`}`

`new` `Child;`

`// 输出:`

`// Base contructor!`

`// Child contructor!`

static

static常规用途是修饰函数或变量使其成为类函数和类变量,也可以修饰函数内变量延长其生命周期至整个应用程序的生命周期。

但是其与self关联上是PHP 5.3以来引入的新用途:静态延迟绑定。

有了static的静态延迟绑定功能,可以在运行时动态确定归属的类。

例如:

`class` `Base {`

`public` `function` `__construct() {`

`echo` `"Base constructor!"``, PHP_EOL;`

`}`

`public` `static` `function` `getSelf() {`

`return` `new` `self();`

`}`

`public` `static` `function` `getInstance() {`

`return` `new` `static``();`

`}`

`public` `function` `selfFoo() {`

`return` `self::foo();`

`}`

`public` `function` `staticFoo() {`

`return` `static``::foo();`

`}`

`public` `function` `thisFoo() {`

`return` `$this``->foo();`

`}`

`public` `function` `foo() {`

`echo`  `"Base Foo!"``, PHP_EOL;`

`}`

`}`

`class` `Child` `extends` `Base {`

`public` `function` `__construct() {`

`echo` `"Child constructor!"``, PHP_EOL;`

`}`

`public` `function` `foo() {`

`echo` `"Child Foo!"``, PHP_EOL;`

`}`

`}`

`$base` `= Child::getSelf();`

`$child` `= Child::getInstance();`

`$child``->selfFoo();`

`$child``->staticFoo();`

`$child``->thisFoo();`

程序输出结果如下:

`Base constructor!`

`Child constructor!`

`Base Foo!`

`Child Foo!`

`Child Foo!`

在函数引用上,self与static的区别是:对于静态成员函数,self指向代码当前类,static指向调用类;对于非静态成员函数,self抑制多态,指向当前类的成员函数,static等同于this,动态指向调用类的函数。

parent、self、static三个关键字联合在一起看挺有意思,分别指向父类、当前类、子类,有点“过去、现在、未来”的味道。

this

self与this是被讨论最多,也是最容易引起误用的组合。

两者的主要区别如下:

this不能用在静态成员函数中,self可以;

对静态成员函数/变量的访问,建议 用self,不要用$this::或$this->的形式;

对非静态成员变量的访问,不能用self,只能用this;

this要在对象已经实例化的情况下使用,self没有此限制;

在非静态成员函数内使用,self抑制多态行为,引用当前类的函数;而this引用调用类的重写(override)函数(如果有的话)。

self的用途

看完与上述三个关键字的区别,self的用途是不是呼之即出?一句话总结,那就是:self总是指向“当前类(及类实例)”。

详细说则是:

替代类名,引用当前类的静态成员变量和静态函数;

抑制多态行为,引用当前类的函数而非子类中覆盖的实现;

槽点

这几个关键字中,只有this要加$符号且必须加,强迫症表示很难受;

静态成员函数中不能通过$this->调用非静态成员函数,但是可以通过self::调用,且在调用函数中未使用$this->的情况下还能顺畅运行。此行为貌似在不同PHP版本中表现不同,在当前的7.3中ok;

在静态函数和非静态函数中输出self,猜猜结果是什么?都是string(4) "self",迷之输出;

return $this instanceof static::class;会有语法错误,但是以下两种写法就正常:

`$class = static::class;`

`return` `$``this` `instanceof` `$class;`

`// 或者这样:`

`return` `$``this` `instanceof` `static;`

所以这是为什么啊?!

`$class = static::class;`

`return` `$``this` `instanceof` `$class;`

`// 或者这样:`

`return` `$``this` `instanceof` `static;`
Image placeholder
小牛
未设置
  86人点赞

没有讨论,发表一下自己的看法吧

推荐文章
Go编程语言教程_2.1. Golang中的关键字

关键字或保留字是用于某些内部过程或表示某些预定义动作的语言中的字。因此,不允许将这些单词用作标识符。这样做会导致编译时错误。 例: //Go程序说明 //使用关键字 packagemain impor

面向对象的封装特性和static关键字笔记

封装流程:1:私有化成员变量,使用private关键字修饰;2:提供公有的get和set方法,在方法体中进行合理值的判断;3:在构造方法中调用set方法进行合理值的判断

面向对象的封装特性和static关键字笔记

static修饰成员变量后,由成员变量层级提升为类层级

Python 教程-了解Python

什么是Python Python能干什么? 有什么特点? 什么是Python 官方介绍: Python是一个易于学习、功能强大的编程语言。它拥有高效高级的数据结构和一种简单有效的面向对象编程的

尴尬了!四分之三的Sybase/ASE用户无意迁往SAP HANA

SAP战略,很大一部与SAP HANA有关。SAPHANA是SAP在2010年发布的一款产品,其全称是SAPHighPerformanceAnalyticApplication,简称SAPHANA,内

Elasticsearch的sql化使用

Elasticsearch-sql的安装、使用本文以Elasticsearch-5.1.2为例elasticsearch-sql下载地址:https://github.com/NLPchina/e..

张小龙:用停留时长衡量一个APP的好坏是错误的!

“这两年,业界目标变成所有APP应该尽可能多地去抓住用户的停留时长,这违背常识。一个用户每天的时间是有限的,技术的使命应该是帮助人类提高效率而不是降低效率。”这是张小龙在微信之夜上的一段讲话。1月9日

女神说不能每张照片P的一样,所以朋友圈开三天可见,用Python一步解决

大家好,我是小三十三,一个刚恰完午饭,正在用刷网页浪费生命的蒟蒻...一堆堆无聊八卦信息的网页内容慢慢使我的双眼模糊,一个哈欠打出了三斤老泪,就在此时我看到了一张图片:是谁!是谁把我女朋友的照片放出来

html和jsp的区别及优缺点

html和jsp的区别:●最简单的区别就是,HTML能直接打开,jsp只能发布到Tomact等服务器上才能打开●定义上HTML页面是静态页面可以直接运行,JSP页面是动态页它运行时需要转换成servl

知了 | 基于NLP的智能问答推荐系统

作者简介:苗贝贝  百度高级研发工程师负责百度智能运维客服平台ChatOps,在时序数据异常检测、文本模式识别、相似度网络等方向也有广泛的实践经验。干货概览通常,客服系统主要有两种应答模式:机器人自动

jquery easyui和bootstrap的区别是什么?

JQueryEasyUIJQueryEasyUI是一组基于jQuery的UI插件集合体,而jQueryEasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者不需要编写复

jquery中attr和prop的区别是什么?

在jQuery中,attr()函数和prop()函数都用于设置或获取指定的属性,它们的参数和用法也几乎完全相同。但不得不说的是,这两个函数的用处却并不相同。下面我们来详细介绍这两个函数之间的区别。jq

PHP 中 bind 的用法 self 和 static 的区别

bind是bindTo的静态版本,因此只说bind吧。(还不是太了解为什么要弄出两个版本)官方文档:复制一个闭包,绑定指定的$this对象和类作用域。其实后半句表述很不清楚。我的理解:把一个闭包转换为

让AI无处不在:滴滴与蚂蚁金服开源共建SQLFlow

2018年1月,Oracle的官方博客上发表了一篇文章,标题是“It’sPervasive:AIIsEverywhere”。作为全球最著名的商业数据库系统提供商,Oracle在这篇文章里历数了AI在企

聊聊chronos的pullFromDefaultCFAndPush

序本文主要研究一下chronos的pullFromDefaultCFAndPushpullFromDefaultCFAndPushDDMQ/carrera-chronos/src/main/java/

引领存储新时代——新华三Primera关键业务智能存储

技术的变革,让我们步入数字智能时代。由数据、AI驱动的智能化产业转型正在如火如荼地进行中,金融、工业、医疗、娱乐……智能改变着一切。在IT对于企业已经如此重要的今天,智能也正改变着支撑企业业务运行的底

企业需要知道的 6个AI/ML关键点

由于人工智能(AI)和机器学习(ML)的迅速发展与应用落地,世界各地的公司正在积极利用AI和ML发展业务,甚至投资数百亿美元。这些技术能够对业务与产生深刻的影响,所以Gartner报告预测,未来将“进

在头条和百度搜索了100个关键词之后,我们发现……

作者|闫丽娇苏琦编辑|苏琦• 常用名词搜索方面,百度站外内容占比更高,内容来源比头条更多元。头条搜索的信息流广告目前还没有接入;• 疑问解答类搜索,百度的内容发散性更杂,而头条在信息准确度上更能理解用

盘点2018:数据库领域关键词“自研” ”融合“ ”崛起“

尽管2019年已然开始,但只要农历春节还没过,就意味着2018年还没有真正结束。回望过去一年,数据库领域发生了哪些有代表性的事件?这些事件背后预示哪些趋势?尽管2019年已然开始,但只要农历春节还没过

张建锋:当代数字化升级的四大关键技术

9月25日,为期三天的2019云栖大会在杭州云栖小镇正式召开,阿里巴巴集团CTO兼阿里云智能总裁张建锋在上午的主会场中发表《构建数字经济基础设施》演讲,提出了当代数字化升级的四大关键技术。阿里巴巴集团

为什么大部分人做不了架构师?这2点是关键

阿里妹导读:选择有时候比努力重要,真正厉害的人不仅仅是埋头苦干,而是会利用好的思维方式、好的方法,看穿事物的本质,顺势而为,找到事情的最优解,并懂得举一反三。架构师是程序员的目标之一,但大多数程序员无

详解 PHP 中的三大经典模式

单例模式 单例模式的含义:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。单例模式的三

详解 PHP 中的三大经典模式

单例模式 单例模式的含义:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。单例模式的三

详解 PHP 反射的基本使用

PHP反射 今天我要给大家讲解的是PHP当中使用非常普遍的高级操作:反射。反射在当今几乎所有的PHP框架或者工具中都占用非常重要的角色,就比如Laravel的容器,容器对于Laravel架构来说极其重

03.4. Go 的 http 包详解

前面小节介绍了Go怎么样实现了Web工作模式的一个流程,这一小节,我们将详细地解剖一下http包,看它到底是怎样实现整个过程的。 Go的http有两个核心功能:Conn、ServeMux Conn的g