转载请注明文章出处:https://tlanyan.me/overload-i...整理思路时想到一个问题:为什么PHP不允许同名函数存在?即禁止其他语言中常见的重载机制?重载和重写首先区分重载和覆盖:重载是指多个同名但参数不同的函数在同一个作用域中共存的现象;重写发生在继承中,是指一个类重新定义父类的功能的现象,也称为重写。重载中提到的参数不同有三种情况:参数个数不同、参数类型不同、参数顺序不同。重写一般是指函数的覆盖,即在子类中重新定义具有相同签名的成员函数(实现抽象函数或接口不算重写),是实现多态的关键技术。成员变量也可以重载/覆盖,但通常不会这样做。说明重载的简单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~]#纳米测试|grepadd0000000000400730t_GLOBAL__sub_I__Z3addii0000000000400851T_Z3adddd00000000004008b1T_Z3adddii000000000040083dT_Z3addii000000000040087dT_Z3addiid最后四行的第三Thecolumncorrespondstothesymbolinformationofthefourfunctionsaftercompilation,_Z3istheprefix,addisthefunctionname,andtheremainingletterdstandsfordouble,i代表int,一一对应life。回到PHP重载。在PHP的函数声明中,不需要声明参数的类型,直接排除了不同参数类型和不同参数顺序的两种重载,只留下不同数量的参数。定义同名但参数个数不同的函数是非法的。这么小的重载要求在PHP中也是非法的!原因是PHP中不允许具有相同名称的函数。如果你想定义一个同名的函数,放弃吧!虽然在大多数情况下用默认参数重载基本就够了,但我还是时不时感到委屈,忍不住想问:为什么PHP不允许(同名函数)重载?!PHP的困难PHP不支持重载同名函数是有原因的。上面说了,PHP函数声明时不需要指定参数类型,重载三种情况中的两种立马废除了。存活参数个数不同的路径不行,为什么?因为在PHP中调用一个函数的时候,传递的参数少一点是不行的;多传几个参数也没问题!举个简单的例子:functionfoo($arg1,$arg2){echo"$arg1,$arg2\n";}//functioncall//toofewparameters,prompt://PHPWarning:Missingargument2forfoo()//PHPNotice:Undefinedvariable:arg2inphpshellcodeonline2foo("tlanyan");//参数个数刚刚好,运行正常foo("hello","tlanyan");//传递更多参数,一切正常foo("hello","tlanyan","niceday");//传递更多参数,一切正常foo("hello","tlanyan","morning","noon"","下午","晚上","晚上");只要不小于声明的个数,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。从兼容性和实用性的角度,我个人认为短时间内重载同名函数的概率很小。PHP中的重载看了上面的内容就说PHP不支持重载。我想任何一个资深的PHP开发者都会不由自主地脱掉拖鞋,然后教你PHP中的重载是什么,并且保证至少有好几种实现方式;官方人员也无力吐槽这种认知:你能仔细看官方文档吗?!官网上有个专区专门用来超载的!由于各种原因,PHP不支持传统的重载,即同名函数的重载,但是PHP支持重载,而且有相当多的手势。简单来说,PHP中主要有以下几种重载方式:默认参数,定义综合函数版本,非必需值在声明时赋默认值;定义一个不声明参数的入口函数,使用func_num_args/func_get_args获取参数个数/数组,然后根据参数个数转发给具体实现的函数;从PHP5.6开始,可以使用变长参数实现重载,func_get_args的另一种形式;对于类中的成员函数,可以通过__call和__callStatic实现重载。如果你知道其他方法,欢迎评论并给出解决方案。综上所述,PHP的特性决定了它不支持重载同名函数,但不代表PHP不支持重载。事实上,PHP可以通过多种方式实现重载,并保持其一贯的简洁性和易用性。谢谢阅读!参考http://php.net/manual/it/lang...
