PHP中的self关键字详解


Posted in PHP onJune 23, 2019

前言

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是被讨论最多,也是最容易引起误用的组合。两者的主要区别如下:

  1. this不能用在静态成员函数中,self可以;
  2. 对静态成员函数/变量的访问,建议 用self,不要用$this::或$this->的形式;
  3. 对非静态成员变量的访问,不能用self,只能用this;
  4. this要在对象已经实例化的情况下使用,self没有此限制;
  5. 在非静态成员函数内使用,self抑制多态行为,引用当前类的函数;而this引用调用类的重写(override)函数(如果有的话)。

self的用途

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

  1. 替代类名,引用当前类的静态成员变量和静态函数;
  2. 抑制多态行为,引用当前类的函数而非子类中覆盖的实现;

槽点

  1. 这几个关键字中,只有this要加$符号且必须加,强迫症表示很难受;
  2. 静态成员函数中不能通过$this->调用非静态成员函数,但是可以通过self::调用,且在调用函数中未使用$this->的情况下还能顺畅运行。此行为貌似在不同PHP版本中表现不同,在当前的7.3中ok;
  3. 在静态函数和非静态函数中输出self,猜猜结果是什么?都是string(4) "self",迷之输出;
  4. return $this instanceof static::class;会有语法错误,但是以下两种写法就正常:
$class = static::class;
return $this instanceof $class;
// 或者这样:
return $this instanceof static;

所以这是为什么啊?!

参考

When to use self over $this?

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
针对初学PHP者的疑难问答(1)
Oct 09 PHP
Php Mssql操作简单封装支持存储过程
Dec 11 PHP
PHP中把对象转换为关联数组代码分享
Apr 09 PHP
PHP用反撇号执行外部命令
Apr 14 PHP
教你在PHPStorm中配置Xdebug
Jul 27 PHP
win7安装php框架Yii的方法
Jan 25 PHP
php preg_match的匹配不同国家语言实例
Dec 29 PHP
浅谈PHP中的错误处理和异常处理
Feb 04 PHP
PHP实现查询手机归属地的方法详解
Apr 28 PHP
PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)
Sep 17 PHP
PHP简单实现正则匹配省市区的方法
Apr 13 PHP
php apache开启跨域模式过程详解
Jul 08 PHP
php面向对象程序设计入门教程
Jun 22 #PHP
PHP字符串中抽取子串操作实例分析
Jun 22 #PHP
微信公众号之主动给用户发送消息功能
Jun 22 #PHP
Yii 使用intervention/image拓展实现图像处理功能
Jun 22 #PHP
PHP实现给定一列字符,生成指定长度的所有可能组合示例
Jun 22 #PHP
PHP中strtr与str_replace函数运行性能简单测试示例
Jun 22 #PHP
PHP判断函数是否被定义的方法
Jun 21 #PHP
You might like
php判断当前操作系统类型
2015/10/28 PHP
详解PHP中的 input属性(隐藏 只读 限制)
2017/08/14 PHP
laravel项目利用twemproxy部署redis集群的完整步骤
2018/05/11 PHP
node.js中的buffer.toString方法使用说明
2014/12/14 Javascript
js光标定位文本框回车表单提交问题的解决方法
2015/05/11 Javascript
jqGrid中文文档之选项设置
2015/12/02 Javascript
JS三级可折叠菜单实现方法
2016/02/29 Javascript
EasyUI为Numberbox添加blur事件的方法
2017/03/05 Javascript
解决vue中post方式提交数据后台无法接收的问题
2018/08/11 Javascript
jQuery实现手风琴效果(蒙版)
2020/01/11 jQuery
javascript实现支付宝滑块验证码效果
2020/07/24 Javascript
[03:12]2016完美“圣”典风云人物:单车专访
2016/12/02 DOTA
使用python实现拉钩网上的FizzBuzzWhizz问题示例
2014/05/05 Python
举例讲解Python中字典的合并值相加与异或对比
2016/06/04 Python
在Pycharm中对代码进行注释和缩进的方法详解
2019/01/20 Python
对python dataframe逻辑取值的方法详解
2019/01/30 Python
Python开启线程,在函数中开线程的实例
2019/02/22 Python
python机器学习库scikit-learn:SVR的基本应用
2019/06/26 Python
django中使用POST方法获取POST数据
2019/08/20 Python
python自动识别文本编码格式代码
2019/12/26 Python
python GUI库图形界面开发之PyQt5信号与槽多窗口数据传递详细使用方法与实例
2020/03/08 Python
pytorch学习教程之自定义数据集
2020/11/10 Python
美国饼干礼物和美食甜点购买网站:Cheryl’s
2020/05/28 全球购物
应届生求职推荐信
2013/10/28 职场文书
超市业务员岗位职责
2013/12/05 职场文书
财政局长自荐信范文
2013/12/22 职场文书
白酒业务员岗位职责
2013/12/27 职场文书
学年自我鉴定
2014/01/16 职场文书
数学国培研修感言
2014/02/13 职场文书
《桃花心木》教学反思
2014/02/17 职场文书
2014年元旦促销活动方案
2014/02/22 职场文书
《学会合作》教学反思
2014/04/12 职场文书
学习优秀共产党员先进事迹思想报告
2014/09/17 职场文书
先进教师个人事迹材料
2014/12/15 职场文书
2015年秋季新学期寄语
2015/03/25 职场文书
vue 自定义组件添加原生事件
2022/04/21 Vue.js