PHP中的self关键字详解

 更新时间:2019年8月17日 19:20  点击:426

前言

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;


总结

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

[!--infotagslink--]

相关文章

  • C#中的静态成员、静态方法、静态类介绍

    本文主要介绍了C#中的静态成员、静态方法、静态类的基础的使用,并做了相关的代码演示,供初学者参考。...2020-06-25
  • Ruby 中的 module_function 和 extend self异同

    本文主要给大家介绍了在Ruby中 module_function 和 extend self的共同点和区别,非常的详细,也很实用,方便大家更好的理解的module_function 和 extend self...2020-06-30
  • SignalR Self Host+MVC等多端消息推送服务(三)

    这篇文章主要为大家详细介绍了SignalR Self Host+MVC等多端消息推送服务的第三篇,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
  • C++类的静态成员初始化详细讲解

    通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化...2020-04-25
  • java 利用反射获取内部类静态成员变量的值操作

    这篇文章主要介绍了java 利用反射获取内部类静态成员变量的值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-04
  • .NET Core 1.0创建Self-Contained控制台应用

    这篇文章主要为大家详细介绍了.NET Core 1.0创建Self-Contained控制台应用的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
  • C++类的静态成员变量与静态成员函数详解

    下面小编就为大家带来一篇C++类的静态成员变量与静态成员函数的文章。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-11-03
  • C++ 类的静态成员深入解析

    在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象...2020-04-25
  • python定义类self用法实例解析

    这篇文章主要介绍了python定义类self用法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-04-22
  • php类中的$this,static,final,const,self这几个关键字使用方法

    php类中的$this,static,final,const,self这几个关键字在项目中经常会用的到,通过本文给大家分享this,static,final,const,self这几个关键字使用方法,对此感兴趣的朋友一起学习吧...2015-12-16
  • Swift 4.2使用self做为变量名浅析

    这篇文章主要给大家介绍了关于Swift 4.2使用self做为变量名的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-30
  • php类中static与self的使用区别浅析

    在阅读一些框架的源码时发现了new static(),和new self(),甚是不解,后来查阅资料,才了解了,所以下面这篇文章主要给大家介绍了关于php类中static与self的使用区别的相关资料,需要的朋友可以参考下...2021-06-21
  • C++ 静态成员的类内初始化详解及实例代码

    这篇文章主要介绍了C++ 静态成员的类内初始化详解及实例代码的相关资料,需要的朋友可以参考下...2020-04-25
  • 老生常谈c++中的静态成员

    有时候需要类的一些成员与类本身相关联,而不是与类的每个对象相关联。比如类的所有对象都要共享的变量,这个时候我们就要用到类的静态成员,今天通过实例代码给大家详细介绍,需要的朋友参考下吧...2021-07-21
  • C++静态成员变量和静态成员函数的使用方法总结

    下面小编就为大家带来一篇C++静态成员变量和静态成员函数的使用方法总结。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
  • SignalR Self Host+MVC等多端消息推送服务(二)

    这篇文章主要为大家详细介绍了SignalR Self Host+MVC等多端消息推送服务的第二篇,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
  • SignalR Self Host+MVC等多端消息推送服务(一)

    这篇文章主要为大家详细介绍了SignalR Self Host+MVC等多端消息推送服务,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
  • php面向对象编程self和static的区别

    这篇文章主要介绍了PHP中static关键字以及与self关键字的区别,本文讲解了static关键字的定义、迟绑定(Late Static Bindings)、以及与self关键字的区别等内容,需要的朋友可以参考下...2016-05-10
  • C++类静态成员与类静态成员函数详解

    静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值...2020-04-25
  • PHP中的self关键字详解

    静态成员函数内不能用this调用非成员函数,但可以用self调用静态成员函数/变量/常量;其他成员函数可以用self调用静态成员函数以及非静态成员函数。随着讨论的深入,发现self并没有那么简单。鉴于此,本文先对几个关键字做对比和区分,再总结self的用法。...2019-08-17