简述PHP的重载,PHP 中的重载

PHP 中的重载

整理思路时想到一个问题: PHP 为什么不允许同名函数存在? 即不允许常见于其他语言的重载机制?

重载和重写

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

用简单的 C 代码来说明重载:intadd(inta,intb){returna+b;}

doubleadd(doublea,doubleb){returna+b;}

doubleadd(inta,intb,doublec){returna+b+c;}

doubleadd(doublea,intb,intc){returna+b+c;}

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

0000000000400730t _GLOBAL__sub_I__Z3addii

0000000000400851T _Z3adddd

00000000004008b1T _Z3adddii

000000000040083d T _Z3addii

000000000040087d T _Z3addiid

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

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

PHP 的苦衷

PHP 不支持同名函数的重载是有原因的. 上面已经提到, PHP 函数声明时不需要指定参数类型, 重载中的三种情况立马废掉两种. 幸存的参数个数不同这一条路也走不通, 为什么呢? 因为 PHP 中调用函数时, 少传参数, 不行; 多传参数, 没问题! 来个简单的例子:functionfoo($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_exists, method_exists,is_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. 从兼容性和实用性考虑, 个人认为短时间内能以同名函数方式重载的概率非常小.

来源: https://juejin.im/post/5b02f0896fb9a07aae157e82

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值