PHP重载基础知识回顾_php技巧

来源:脚本之家  责任编辑:小易  

PHP不支持重载,但是2113可以利用灵活性模拟5261JAVA的重载,另外PHP是支持重4102写的。模拟重载的例子1653我写了个,你参考一下 function overloadTest(){ $name = "overload".func_num_args(); $name(); } function overload0(){ echo 'overload0'; } function overload1(){ echo 'overload1'; } function overload2(){ echo 'overload2'; } overloadTest(); //overload0 overloadTest(1); //overload1 overloadTest(1,1); //overload2希望对你有帮助!,只有 test 方法不存在的时2113候, 才会调用 __call你已经定义了5261 test 方法, 所以不会去4102触发 __call所以这种情况1653,一般的写法是class Test {private function _test0(){ echo "No argument."';}private function _test1($arg1){ echo $arg1;}private function _test2($arg1, $arg2){ echo $arg1, " -- " , $arg2;}public function __call($func, $args){ if($func == 'test'){ $number = func_num_args(); $args = func_get_args(); if($number == 1){ return $this->_test1($args[0]); }elseif($number == 2){ return $this->_test2($args[0], $args[1]); }else{ return $this->_test0(); } }}}www.zgxue.com防采集请勿采集本网。

重载和重写

针对不同参数形式写出的多个功能类似名字一样的函数。 比如 sort(int a,int b){} sort(double c,double d,double f){} 这两个函数就是重载关系

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

php 作为一种弱类型语言,本身不能像强类型如java ,c++那样,直接的实现重载。不过可以通过一些方法,间接的实现重载。 使用一个统一的函数来实现重载。该

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

LZ是指override可以的, 只要同名就可以了呀. 但最好是使用PHP5中的__construct构造函数不知道是不是指这个, LZ可以贴个例子代码

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; }

php可以通过类实现方法的重载,主要通过魔术方法:使用 __get(),__set(),__isset() 和 __unset() 进行属性重载,看下面例子: ==============

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

针对不同参数形式写出的多个功能类似名字一样的函数。 比如 sort(int a,int b){} sort(double c,double d,double f){} 这两个函数就是重载关系

[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 2foo("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中主要有以下几种重载方式:

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

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

总结

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

感谢阅读!

以上就是PHP重载基础知识回顾的详细内容,更多关于PHP 重载的资料请关注真格学网其它相关文章! 您可能感兴趣的文章:解决PHP Opcache 缓存刷新、代码重载出现无法更新代码的问题php 使用 __call实现重载功能示例PHP面向对象程序设计模拟一般面向对象语言中的方法重载(overload)示例PHP面相对象中的重载与重写PHP中子类重载父类的方法【parent::方法名】PHP面向对象编程之深入理解方法重载与方法覆盖(多态)php函数重载的替代方法--伪重载详解php继承中方法重载(覆盖)的应用场合PHP使用方法重载实现动态创建属性的get和set方法PHP利用func_get_args和func_num_args函数实现函数重载实例php面向对象全攻略 (八)重载新的方法php面向对象的方法重载两种版本比较

php面向对象(OOP)编程完全2113教程:12.重载新的方法5261  在学习PHP 这种4102语言中你会发现, PHP中的方法是不能重载的1653, 所谓的方法重载就是定义相同的方法名,通过“参数的个数“不同或“参数的类型“不同,来访问我们的相同方法名的不同方法。但是因为PHP是弱类型的语言, 所以在方法的参数中本身就可以接收不同类型的数据,又因为PHP的方法可以接收不定个数的参数,所以通过传递不同个数的参数调用不相同方法名的不同方法也是不成立的。所以在PHP里面没有方法重载。不能重载也就是在你的项目中不能定义相同方法名的方法。另外,因为PHP没有名子空间的概念,在同一个页面和被包含的页面中不能定义相同名称的方法, 也不能定义和PHP给我提供的方法的方法重名,当然在同一个类中也不能定义相同名称的方法。  我们这里所指的重载新的方法所指的是什么呢?其实我们所说的重载新的方法就是子类覆盖父类的已有的方法,那为什么要这么做呢?父类的方法不是可以继承过来直接用吗?但有一些情况是我们必须要覆盖的,比如说我们前面提到过的例子里面, “Person”这个人类里面有一个“说话”的方法,所有继承“Person”类的子类都是可以“说话”的, 我们“Student”类就是“Person”类的子类,所以“Student”的实例就可以“说话“了, 但是人类里面“说话”的方法里面说出的是“Person”类里面的属性, 而“Student”类对“Person”类进行了扩展,又扩展出了几个新的属性,如果使用继承过来的“say()”说话方法的话,只能说出从“Person”类继承过来的那些属性,那么新扩展的那些属性使用这个继承过来的“say()”的方法就说不出来了,那有的人就问了,我在“Student”这个子类中再定义一个新的方法用于说话,说出子类里面所有的属性不就行了吗?一定不要这么做, 从抽象的角度来讲, 一个“学生”不能有两种“说话”的方法,就算你定义了两个不同的说话的方法,可以实现你想要的功能,被继承过来的那个“说话“方法可能没有机会用到了,而且是继承过来的你也删不掉。这个时候我们就要用到覆盖了。虽然说在PHP里面不能定义同名的方法, 但是在父子关系的两个类中,我们可以在子类中定义和父类同名的方法,这样就把父类中继承过来的方法覆盖掉了。代码 <? //定义一个"人"类做为父类 class Person { //下面是人的成员属性 var $name; //人的名子 var $sex; //人的性别 var $age; //人的年龄 //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值 function __construct($name, $sex, $age) { $this->name=$name; $this->sex=$sex; $this->age=$age; } //这个人可以说话的方法, 说出自己的属性 function say() { echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age; } } class Student extends Person { var $school; //学生所在学校的属性 //这个学生学习的方法 function study() { echo "我的名子叫:".$this->name." 我正在".$this->school." 学习"; } //这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法 function say() { echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."我在".$this->school."上学; } }?>上面的例子, 我们就在“Student”子类里覆盖了继承父类里面的”say()”的方法,通过覆盖我们就实现了对“方法”扩展。但是,像这样做虽然解决了我们上面说的问题,但是在实际开发中,一个方法不可能就一条代码或是几条代码,比如说“Person”类里面的“say()”方法有里面有100条代码,如果我们想对这个方法覆盖保留原有的功能外加上一点点功能,就要把原有的100条代码重写一次, 再加上扩展的几条代码,这还算是好的,而有的情况,父类中的方法是看不见原代码的,这个时候你怎么去重写原有的代码呢?我们也有解决的办法,就是在子类这个方法中可以调用到父类中被覆盖的方法, 也就是把被覆盖的方法原有的功能拿过来再加上自己的一点功能,可以通过两种方法实现在子类的方法中调用父类被覆盖的方法:一种是使用父类的“类名::“来调用父类中被覆盖的方法;一种是使用“parent::”的方试来调用父类中被覆盖的方法;代码 class Student extends Person{ var $school; //学生所在学校的属性 //这个学生学习的方法 function study() { echo "我的名子叫:".$this->name." 我正在".$this->school." 学习"; } //这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法 function say() { //使用父类的"类名::"来调用父类中被覆盖的方法; // Person::say(); //或者使用"parent::"的方试来调用父类中被覆盖的方法; parent::say(); //加上一点自己的功能 echo "我的年龄是:".$this->age."我在".$this->school."上学."; }}  现在用两种方式都可以访问到父类中被覆盖的方法,我们选那种方式最好呢?用户可能会发现自己写的代码访问了父类的变量和函数。如果子类非常精炼或者父类非常专业化的时候尤其是这样。 不要用代码中父类文字上的名字,应该用特殊的名字 parent,它指的就是子类在 extends 声明中所指的父类的名字。这样做可以避免在多个地方使用父类的名字。如果继承树在实现的过程中要修改,只要简单地修改类中 extends 声明的部分。  同样,构造方法在子类中如果没有声明的话,也可以使用父类中的构造方法,如果子类中重新定义了一个构造方法也会覆盖掉父类中的构造方法,如果想使用新的构造方法为所有属性赋值也可以用同样的方式。代码 class Student extends Person{ var $school; //学生所在学校的属性 function __construct($name, $sex, $age, $school) { //使用父类中的方法为原有的属性赋值 parent::__construct($name, $sex, $age); $this->school=$school; } //这个学生学习的方法 function study() { echo "我的名子叫:".$this->name." 我正在".$this->school." 学习"; } //这个人可以说话的方法, 说出自己的属性 function say() { parent::say(); //加上一点自己的功能 echo "我的年龄是:".$this->age."我在".$this->school."上学."; } },php 5.3 支持类的2113方法的重载5261,但不支持函数的重4102载。class test { function a() { echo '无参数调1653用'; } function a($val) { echo '带参数'.$val.'调用'; }}$obj = new test;$obj->a();$obj->a('v');内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • php依赖注入(di)和控制反转(ioc)详解
  • php+resumablejs实现的分块上传 断点续传功能示例
  • php判断一个变量是否为整数、正整数的方法示例
  • php中利用str_pad函数生成数字递增形式的产品编号
  • php入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等
  • php图像处理类代码分享
  • php读取、解析eml文件及生成网页的方法示例
  • php7.1实现的aes与rsa加密操作示例
  • 最常用的8款php调试工具
  • php中iconv函数使用方法
  • php怎么方法重载
  • PHP怎么重载已经存在的方法
  • PHP重载 有什么用
  • php 到底可不可以重载
  • PHP重载到底是什么意思
  • php为什么不支持函数重载啊?
  • PHP构造器是不是不能重载? - PHP进阶讨论
  • php6有没有实现方法的重载
  • php重载是什么意思
  • php前台用reload()重载页面重载前的session中存储...
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全php基础php技巧php实例php文摘php模板首页php编程解决php opcache 缓存刷新、代码重载出现无法更新代码的问题php 使用 __call实现重载功能示例php面向对象程序设计模拟一般面向对象语言中的方法重载(overload)示例php面相对象中的重载与重写php中子类重载父类的方法【parent::方法名】php面向对象编程之深入理解方法重载与方法覆盖(多态)php函数重载的替代方法--伪重载详解php继承中方法重载(覆盖)的应用场合php使用方法重载实现动态创建属性的get和set方法php利用func_get_args和func_num_args函数实现函数重载实例php面向对象全攻略 (八)重载新的方法php面向对象的方法重载两种版本比较php依赖注入(di)和控制反转(ioc)详解php+resumablejs实现的分块上传 断点续传功能示例php判断一个变量是否为整数、正整数的方法示例php中利用str_pad函数生成数字递增形式的产品编号php入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等php图像处理类代码分享php读取、解析eml文件及生成网页的方法示例php7.1实现的aes与rsa加密操作示例最常用的8款php调试工具php中iconv函数使用方法php中json_decode()和json_encodphp 数组和字符串互相转换实现方php中使用curl实现get和post请求php中iconv函数使用方法php日期转时间戳,指定日期转换成php 页面跳转到另一个页面的多种php中文处理 中文字符串截取(mb_php 字符串中是否包含指定字符串php下intval()和(int)转换使用与利用phpexcel实现excel数据的导入adodb结合smarty使用~超级强php7 错误处理机制修改实例分析让php支持页面回退的两种方法[转]php如何读取由javascript设置的cookiephp及zend engine的线程安全模型分析使用php socke 向指定页面提交数据php实现的mysqldb读写分离操作类示例php传参之传值与传址的区别php求斐波那契数的两种实现方式【递归与递php查看当前session的id实例
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved