php中self::能调用子类重写的方法吗_静态绑定与重写关系【介绍】

千婷酱_5940

千婷酱_5940

2026-01-01

679人浏览

原创

self:: 不调用子类重写的方法,因其在编译期绑定到当前代码所在类,而非运行时对象类;static:: 才支持后期静态绑定,可调用子类重写的方法。

php中self::能调用子类重写的方法吗_静态绑定与重写关系【介绍】

self:: 不能调用子类重写的方法 —— 它始终绑定到**当前书写该代码的类**,而非运行时实际对象的类。这是 PHP 静态绑定(early binding)的典型表现,和 static:: 的后期静态绑定(late static binding)有本质区别。

为什么 self:: 不会调用子类重写的方法?

因为 self:: 在编译期就确定了目标类,不随继承链动态变化。哪怕你在父类里写 self::foo(),子类继承并重写了 foo(),只要调用点在父类定义中,self:: 仍指向父类本身。

  • 它不是“当前实例所属类”,而是“当前代码所在类”
  • 与 $this-> 不同,self:: 不依赖对象实例,甚至可在静态上下文中使用
  • 重写(override)只对 public/protected 实例方法生效;而 self:: 调用的是静态解析出的类中的方法,不管子类有没有重写

self:: 和 static:: 在方法调用上的关键差异

二者都可用于静态方法调用,但绑定时机不同:

  • self::method() → 编译时绑定到写这行代码的类(比如 Parent)
  • static::method() → 运行时绑定到“最初调用该继承链的类”(即 get_called_class() 返回的类)
  • 只有 static:: 才能触发子类对静态方法或非静态方法的重写(前提是方法可被覆盖)
class Parent {
    public static function who() {
        echo __CLASS__;
    }
    public static function testSelf() {
        self::who();   // 输出 Parent
    }
    public static function testStatic() {
        static::who(); // 输出 Child(若 Child::testStatic() 被调用)
    }
}

class Child extends Parent {
    public static function who() {
        echo __CLASS__;
    }
}

Child::testSelf();   // 输出:Parent
Child::testStatic(); // 输出:Child

哪些情况会让 self:: 看似“调用了子类方法”?

那通常不是 self:: 的功劳,而是以下几种常见误判:

btpanel phpsite 宝塔面板PHP网站
btpanel phpsite 宝塔面板PHP网站

宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理

下载
  • 子类没有重写该方法,self:: 顺延调用父类实现(看起来“有效”,实则未发生重写)
  • 方法是 final 或 private,根本不可被重写,子类里的同名方法其实是独立新方法
  • 混淆了 self:: 和 $this->:后者确实会走虚函数机制,调用子类重写的实例方法
  • 用了 traits 或别名覆盖,但底层仍不是 self:: 动态寻址

什么时候该坚持用 self::?

当你**明确需要锁定到当前类的行为**,防止被继承破坏逻辑时:

  • 工具型静态方法(如 self::validateEmail()),不应被子类改变语义
  • 构造中间状态的私有静态辅助方法(self::buildConfig())
  • 配合 final 类使用,此时 self:: 和 static:: 效果一致,但语义更清晰
  • 性能敏感场景(极微小差异):self:: 略快,因无需运行时查 get_called_class()

真正容易被忽略的点是:很多开发者以为把 self:: 换成 static:: 就能“支持继承”,却没检查目标方法是否为 public/protected、是否被正确重写、以及是否在静态上下文中被调用 —— 后者一旦出错,直接抛 Strict Standards 或 Fatal error: Cannot make static method non-static。

php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.18

1029

5

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.25

3200

5

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

2026.10.28

60

16

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

2026.10.28

40

15

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

2026.10.28

140

10

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

2026.10.22

140

11

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

2026.10.22

120

10

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

2026.10.22

80

15

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

2026.10.22

40

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习