之前有人询问 self 关键字的用法,答案是比较明显的:静态成员函数内不能用 this 调用非成员函数,但可以用 self 调用静态成员函数/变量/常量;其他成员函数可以用 self 调用静态成员函数以及非静态成员函数。随着讨论的深入,发现 self 并没有那么简单。鉴于此,本文先对几个关键字做对比和区分,再总结 self 的用法。

parentstatic 以及 this 的区别

要想将彻底搞懂 self ,要与 parentstatic 以及 this 区分开。以下分别做对比。

parent

selfparent 的区分比较容易: 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!

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

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

this

selfthis 是被讨论最多,也是最容易引起误用的组合。两者的主要区别如下:

  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;

很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的加群(点击→)677079770

PHP 的 self 关键字用法的更多相关文章

  1. ava下static关键字用法详解

    Java下static关键字用法详解 本文章介绍了java下static关键字的用法,大部分内容摘自原作者,在此学习并分享给大家. Static关键字可以修饰什么? 从以下测试可以看出, static ...

  2. 巨人大哥谈Java中的Synchronized关键字用法

    巨人大哥谈Java中的Synchronized关键字用法 认识synchronized 对于写多线程程序的人来说,经常碰到的就是并发问题,对于容易出现并发问题的地方价格synchronized基本上就 ...

  3. synchronized关键字用法

    看到网上很多讲synchronized关键字用法的文章,说的都很有道理,也很深刻,但是看完总感觉脑袋里还是有点乱乱的.经过一番自己的思考后,想从自己的思考角度出发,来说一说synchronized关键 ...

  4. Java-Runoob-高级教程-实例-方法:09. Java 实例 – continue 关键字用法-un

    ylbtech-Java-Runoob-高级教程-实例-方法:09. Java 实例 – continue 关键字用法 1.返回顶部 1. Java 实例 - continue 关键字用法  Java ...

  5. Java-Runoob-高级教程-实例-方法:08. Java 实例 – break 关键字用法

    ylbtech-Java-Runoob-高级教程-实例-方法:08. Java 实例 – break 关键字用法 1.返回顶部 1. Java 实例 - break 关键字用法  Java 实例 Ja ...

  6. Java-Runoob-高级教程-实例-方法:07. Java 实例 – instanceOf 关键字用法

    ylbtech-Java-Runoob-高级教程-实例-方法:07. Java 实例 – instanceOf 关键字用法 1.返回顶部 1. Java 实例 - instanceof 关键字用法   ...

  7. C#中var关键字用法分析

    原文连接 本文实例分析了C#中var关键字用法.分享给大家供大家参考.具体方法如下: C#关键字是伴随着.NET 3.5以后,伴随着匿名函数.LINQ而来, 由编译器帮我们推断具体的类型.总体来说,当 ...

  8. sql server if exists和 if not exists 的关键字用法

    if exists和if not exists关键字用法   1.介绍  if not exists 即如果不存在,if exists 即如果存在 2.使用  a.判断数据库不存在时  if not ...

  9. Java 实例 - instanceof 关键字用法

    Java 实例 - instanceof 关键字用法 instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符. instanceof 是 Java 的保留关键 ...

  10. C#中default 、base 、this关键字用法简介

     C#中default关键字用法简介 default 关键字可在switch语句或泛型代码中使用.switch语句:指定默认标签.泛型代码:指定类型参数的默认值.对于引用类型为空,对于值类型为零swi ...

随机推荐

  1. 开普勒云平台:如何配置gitlab与Jenkins

    一.Kplcloud是什么? kplcloud是一个基于Kubernetes的轻量级PaaS平台,通过可视化的界面对应用进行管理,降低应用容器化的对度,从而减少应用容器化的时间成本. Kplcloud ...

  2. spring boot 整合JPA多数据源

    上个文章介绍了spring boot在使用Mybatis持久化技术的时候如何使用多数据源,今天再补充一个使用spring data jpa实现多数据源的使用情况,JPA是一套数据库持久化规范,或者称之 ...

  3. 课堂动手动脑验证以及自定义异常类实现对异常处理——java异常类

    异常(exception):发生在程序执行期间,表明出现了一个非法运行的情况.许多JDK中的方法在检测到非法情况时,都会抛出一个异常对象.例如:数组越界和被0除. 代码验证: package test ...

  4. 三、进程和线程、协程在python中的使用

    三.进程和线程.协程在python中的使用 1.多进程一般使用multiprocessing库,来利用多核CPU,主要是用在CPU密集型的程序上,当然生产者消费者这种也可以使用.多进程的优势就是一个子 ...

  5. Spring Boot项目在多环境下(开发、生产或测试环境)调用不同配置文件方式

    写在前面 最近由于项目要求,原先的项目只有开发环境的项目配置,后来不利于线上测试,于是,最近对于SpringBoot这部分多环境配置在网上查找了相关资料,并实现了配置,于是为了防止遗忘,特在此进行总结 ...

  6. Spring使用@Async注解

    本文讲述@Async注解,在Spring体系中的应用.本文仅说明@Async注解的应用规则,对于原理,调用逻辑,源码分析,暂不介绍.对于异步方法调用,从Spring3开始提供了@Async注解,该注解 ...

  7. js原生图片懒加载 或 js原生图片预加载,html标签自定义属性

    使用原声js来实现图片预加载,或图片懒加载,小伙伴们可以根据项目需要来结合vue或者是react来进行修改. 一.什么是图片懒加载或什么是图片预加载 当访问一个页面的时候,先把img元素或是其他元素的 ...

  8. CSPS模拟 74

    T1 贪心,如果用set考虑一下multi. T2 难道是我的疑问都太过sb? 从来没人愿意认真思考一下我的问题. 更好,思考量这东西本该我自己来补. 设$dp[i][j]$为i个点的森林,j个点在特 ...

  9. Docker的centos7容器中如何安装mongodb

    下载安装包: wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.2.12.tgz 解压安装包 tar -zxvf mongodb ...

  10. 【IOS开发—视图】

    一.UIWindow对象 每一个app都有一个UIWindow对象,它像一个容器一样,用来包含应用中的所有视图,应用会在启动时创建并设置UIWindow对象. - (BOOL)application: ...