PHP重载基础知识回顾


Posted in PHP onSeptember 10, 2020

重载和重写

先区分一下重载(overload)和重写(override):重载指多个名字相同,但参数不同的函数在同一作用域并存的现象;重写出现在继承中,指子类重定义父类功能的现象,也被称为覆盖。重载中说的参数不同有三种情况:参数个数不同,参数类型不同,参数顺序不同。重写一般指函数的覆盖,即相同签名的成员函数在子类中重新定义(实现抽象函数或接口不是重写),是实现多态(polymorphism)的一种关键技术。成员变量也可以重载/覆盖,但一般不会这么做。

用简单的C代码来说明重载:

int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
double add(int a, int b, double c) { return a + b + c; }
double add(double a, int b, int c) { return a + b + c; }

第一个函数为参考基准,其他三个对应重载的三种情形。函数重载多见于强类型语言,编译后函数在函数符号表的名称一般是函数名加参数类型。上面的四个函数,g++编译后,nm命令查看符号表中的名字,输出如下:

[tlanyan@server ~]# nm test | grep add
0000000000400730 t _GLOBAL__sub_I__Z3addii
0000000000400851 T _Z3adddd
00000000004008b1 T _Z3adddii
000000000040083d T _Z3addii
000000000040087d T _Z3addiid

最后四行的第三列对应编译后四个函数的符号信息,_Z3为前缀,add是函数名,剩下的字母d代表double,i代表int,与生命一一对应。

再回到PHP的重载。PHP的函数声明中参数无需声明类型,直接排除参数类型不同、参数顺序不同两种重载,只剩下参数个数不同一条路可走。定义一个参数个数不同名字相同的函数,这么一个小小的重载要求,在PHP中也是不合法的!原因是PHP中不允许同名函数存在,想定义重名函数,死心吧!虽然大多数情况下以默认参数方式实现重载基本上够用,但不时还会觉得憋屈,忍不住想问一句:PHP为什么不允许(同名函数)重载啊?!

PHP的苦衷

PHP不支持同名函数的重载是有原因的。上面已经提到,PHP函数声明时不需要指定参数类型,重载中的三种情况立马废掉两种。幸存的参数个数不同这一条路也走不通,为什么呢?因为PHP中调用函数时,少传参数,不行;多传参数,没问题!来个简单的例子:

function foo($arg1, $arg2) {
  echo "$arg1, $arg2\n";
}

// 函数调用
// 参数过少,提示:
//PHP Warning: Missing argument 2 for foo()
// PHP Notice: Undefined variable: arg2 in php shell code on line 2
foo("tlanyan");

// 参数个数正好,运行正常
foo("hello", "tlanyan");

// 多传参数,运行正常
foo("hello", "tlanyan", "nice day");

// 传更多参数,也一切正常
foo("hello", "tlanyan", "morning", "noon", "afternoon", "evening", "night");

只要个数不小于声明的,传多少参数PHP不管。所以参数个数不同,在PHP中不足以区分函数。

个人认为另一个不允许名函数存在的重要原因是function_existsmethod_existsis_callable这些API的存在。作为简单易用的语言,PHP为开发人员提供了查询函数名是否存在/可用的便利API,这在编程语言中很少见(尤其是get_defined_functions这类API)。可以看到,这些API都不需要参数信息。如果能定义参数不同的重载函数,这些API都要跟着改,势必引入额外的复杂性。正所谓鱼与熊掌不可兼得,方便你用时没想到参数不同,不方便你定义就抱怨,好像不好吧?

PHP5引入了反射API,这是非常强大的类型信息查询工具。就函数声明而言,ReflectionMethod/ReflectionFunction类的getParameters/getNumberOfParameters/getNumberOfRequiredParameters等API,功能上甩function_exists等好几条街。有了反射机制,按理说function_exists这些API可以安心的退休。虽然反射这一套东西功能强大,但远没有旧式API简单好用。再加上看看市面上的代码,有多少类库和框架依赖旧式API。从兼容性和实用性考虑,个人认为短时间内能以同名函数方式重载的概率非常小。

PHP中的重载

只看完上面的内容就说PHP不支持重载,我想随便一个资深的PHP开发都会不由自主的取下拖鞋,然后教你什么是PHP中的重载,并保证至少有好几种实现方法;官方人员对这种认知估计也无力吐槽:能不能好好看官方文档?!官网中可是有一节专门讲重载!

因为种种原因,PHP不支持传统的重载,也就是同名函数的重载,但PHP是支持重载的,而且姿势还不少。简单来说,PHP中主要有以下几种重载方式:

  1. 默认参数,定义一个全面的函数版本,不是必须的值在声明时赋予默认值;
  2. 定义一个不声明参数的入口函数,函数内使用func_num_args/func_get_args获取参数个数/数组,然后根据参数个数转发到具体实现的函数;
  3. 自PHP5.6起,可以用变长参数实现重载,func_get_args的另一种形式;
  4. 对于类中的成员函数,可以通过__call和__callStatic实现重载。

如果你还知道其他方式,欢迎评论给出方案。

总结

PHP的特性决定了其不支持同名函数方式的重载,但并不意味着PHP不支持重载。实际上PHP可以多种方式实现重载,并保持其一贯的简单易用性。

感谢阅读!

以上就是PHP重载基础知识回顾的详细内容,更多关于PHP 重载的资料请关注三水点靠木其它相关文章!

PHP 相关文章推荐
php设计模式 Template (模板模式)
Jun 26 PHP
作为PHP程序员应该了解MongoDB的五件事
Jun 03 PHP
php-cli简介(不会Shell语言一样用Shell)
Jun 03 PHP
PHP中上传多个文件的表单设计例子
Nov 19 PHP
php输出指定时间以前时间格式的方法
Mar 21 PHP
PHP实现可自定义样式的分页类
Mar 29 PHP
joomla组件开发入门教程
May 04 PHP
php 微信开发获取用户信息如何实现
Dec 13 PHP
PHP数组操作实例分析【添加,删除,计算,反转,排序,查找等】
Dec 24 PHP
什么是PHP文件?如何打开PHP文件?
Jun 27 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
Jun 16 PHP
Laravel获取所有的数据库表及结构的方法
Oct 10 PHP
PHP反射基础知识回顾
Sep 10 #PHP
PHP获取类私有属性的3种方法
Sep 10 #PHP
php实现图片压缩处理
Sep 09 #PHP
如何在PHP中读写文件
Sep 07 #PHP
PHP延迟静态绑定使用方法实例解析
Sep 05 #PHP
PHP autoload使用方法及步骤详解
Sep 05 #PHP
PHP数组访问常用方法解析
Sep 05 #PHP
You might like
基于mysql的bbs设计(四)
2006/10/09 PHP
javascript一元操作符(递增、递减)使用示例
2013/08/07 Javascript
js调用打印机打印网页字体总是缩小一号的解决方法
2014/01/24 Javascript
JavaScript正则表达式之multiline属性的应用
2015/06/16 Javascript
jQuery插件扩展测试实例
2016/06/21 Javascript
详解Angular2 之 结构型指令
2017/06/21 Javascript
React Native中NavigatorIOS组件的简单使用详解
2018/01/27 Javascript
在vue中使用vue-echarts-v3的实例代码
2018/09/13 Javascript
webpack3里使用uglifyjs压缩js时打包报错的解决
2018/12/13 Javascript
vue输入节流,避免实时请求接口的实例代码
2019/10/30 Javascript
vue实现页面切换滑动效果
2020/06/29 Javascript
[29:59]完美世界DOTA2联赛PWL S3 Forest vs access 第二场 12.11
2020/12/13 DOTA
Python实现监控程序执行时间并将其写入日志的方法
2015/06/30 Python
Python的装饰器用法学习笔记
2016/06/24 Python
python 读取视频,处理后,实时计算帧数fps的方法
2018/07/10 Python
Python Django 页面上展示固定的页码数实现代码
2019/08/21 Python
Python三元运算与lambda表达式实例解析
2019/11/30 Python
基于打开pycharm有带图片md文件卡死问题的解决
2020/04/24 Python
通过自学python能找到工作吗
2020/06/21 Python
基于Python 的语音重采样函数解析
2020/07/06 Python
Python用K-means聚类算法进行客户分群的实现
2020/08/23 Python
Python如何获取文件路径/目录
2020/09/22 Python
通过一张图教会你CSS3倒影的实现
2017/09/26 HTML / CSS
LTD Commodities:礼品,独特发现,家居装饰,家用器皿
2017/08/11 全球购物
Dr. Martens马汀博士澳大利亚官网:马丁靴鼻祖
2019/07/02 全球购物
正宗的澳大利亚Ugg靴子零售商:UGG Express
2020/04/19 全球购物
英文自荐信
2013/12/15 职场文书
适用于所有创业者的创业计划书
2014/02/05 职场文书
经理管理专业毕业自荐书范文
2014/02/12 职场文书
卖车协议书
2014/04/21 职场文书
村委会换届选举方案
2014/05/03 职场文书
2014年妇幼保健工作总结
2014/12/08 职场文书
2015年社区创卫工作总结
2015/04/21 职场文书
《敬重卑微》读后感3篇
2019/11/26 职场文书
详解Java实现设计模式之责任链模式
2021/06/23 Java/Android
golang生成并解析JSON
2022/04/14 Golang