PHP面向对象编程之深入理解方法重载与方法覆盖(多态)
《PHP面向对象编程之深入理解方法重载与方法覆盖(多态)》要点: 什么是多态? 多态(Polymorphism)按字面的意思便是“多种状态”.在面向对象语言中,接口的多种不同的实现方式即为多态.引用Charlie Calverts对多态的描述――多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4编程技术内幕”).简单的说,便是一句话:允许将子类类型的指针赋值给父类类型的指针(没错这段话来自百度百科).那么多态的作用是什么,它有什么实际开发价值呢?在实际的应用开发中,采用面向对象中的多态主要在于可以将不同的子类对象都当作一个父类来处理,并且可以屏蔽不同子类对象之间所存在的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化. 下面便是PHP中多态的两个实现? 办法重载(overload) 重载是类的多态的一种实现.函数重载指一个标识符被用作多个函数名,且能够通过函数的参数个数或参数类型将这些同名的函数区分开来,调用不发生混淆.即当调用的时候,虽然办法名字相同,但根据参数的不同可以自动调用相应的函数. class A{ public function test(){ echo "test1"; } public function test($a){ echo "test2"; } } $a=new A(); $a->test(); $a->test($a); 假如php直接支持办法重载的话.那么上面的例子执行后传参和不传参就会返回不同的值.然而php并不直接支持重载,这就意味着你如果直接按上面这样定义的话,就会报错的.会报什么错呢?会报如下的错误. ? 这意思便是不能重复定义A函数,报错的行数也正是下面这行.PHP教程 public function test($a){ 所以说php是并不直接支持重载的.合着说了这么半天php并不支持..别急,我说的是并不直接支持,所以说是我们可以让php间接支持.这时候就要用到一个函数来支持重载了.就是__call().__call()办法必须带有两个参数.第一个包含了被调用的办法名称,而第二个参数包含了传递给该办法的参数数组.可以通过这个办法实现类似于函数重载的功能.看下面的代码. public function __call($method,$p) { if($method=="display"){ if(is_object($p[0])){ $this->displayObject($p[0]); }else if(is_array($p[0])){ $this->displayArray($p[0]); }else{ $this->displayScalar($p[0]); } } } //下面是对上面定义的调用 $ov=new overload; $ov->display(array(1,2,3)); $ov->display('cat'); 定义办法的时候,可以看到有三个分支,如果一个对象传递给display()办法,就调用的是displayObject()办法;如果传递的是一个数组,调用displayArray();传递的是其他的内容的话,则调用的是displayScalar()办法...可以看到下面调用时,第一个是传递了一个数组,则调用displayArray().第二个传入的不是对象也不是数组,则属于其他内容,调用的是displayScalar()办法.所以这样子就用__call()办法实现了类似于其他语言的办法重载. 办法覆盖(override) 所谓覆盖,从本质上来说就是重写.就是当子类继承父类的一些办法后,子类又在其内部定义了相同的办法,则这个新定义的办法会覆盖继承而来的父类的办法,子类只能调用其内部定义的办法. 有以下几点要求: 1.当一个父类和子类有一个办法,参数和名字完全一致,那么子类办法会覆盖父类的办法. 2.在实行方法覆盖的时候,拜访修饰符可以是不一样的,但是子类的拜访范围必须大于等于父类的拜访范围. 3.要求参数和名字一样.并不是要求子类,父类名称雷同. 下面是对这几点的解释: 第一点,必须参数一致,才会实现办法覆盖.当参数个数不一致,则会报错(这就牵扯到上面说所得办法重载).当办法名字不一致,就不会覆盖,只是子类新定义的办法.; 第二点,这是php这些语言设计时的规定吧.我是这么理解的是拜访高一层的东西比较容易,如果再去拜访底层的东西权限肯定要高一些. 看代码:PHP教程 class people{ protected function sing(){ echo "人唱歌"; } } class woman extends people{ public function sing(){ echo "女人唱歌"; } } $woman1=new woman(); $woman1->sing(); 这样很正常的可以输出“女人唱歌”.但当把woman里的sing()方法改为proctcted,父元素改成public()时,即将父类的拜访权限设置的大于子类后,就会报下面的错误. ? ?第三点,是要求参数和名字一样,具体便是要求参数的个数与父类相同,而并不是参数名称一致.即传递的参数名字可以为任意,只要保证传递的个数相同即可. 以上内容简单介绍了PHP语言中多态的两个实现.PHP教程 PS:重写、覆盖、重载、多态几个概念的区别阐发PHP教程 override->重写(=笼罩)、overload->重载、polymorphism -> 多态 override是重写(覆盖)了一个办法,以实现不同的功能.一般是用于子类在继承父类时,重写(重新实现)父类中的办法. ?? 1、重写方法的参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载. overload是重载,一般是用于在一个类内实现若干重载的办法,这些办法的名称相同而参数形式不同.PHP教程 重载的规矩:PHP教程 ?? 1、在使用重载时只能通过相同的方法名、不同的参数形式实现.不同的参数类型可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样); 多态的概念比较复杂,有多种意义的多态,一个有趣但不严谨的说法是:继承是子类使用父类的办法,而多态则是父类使用子类的办法. 一般,我们使用多态是为了避免在父类里大量重载引起代码痴肥且难于维护.PHP教程 举个例子:PHP教程 public class Shape { public static void main(String[] args){ Triangle tri = new Triangle(); System.out.println("Triangle is a type of shape? " + tri.isShape());// 继承 Shape shape = new Triangle(); System.out.println("My shape has " + shape.getSides() + " sides."); // 多态 Rectangle Rec = new Rectangle(); Shape shape2 = Rec; System.out.println("My shape has " + shape2.getSides(Rec) + " sides."); //重载 } public boolean isShape(){ return true; } public int getSides(){ return 0 ; } public int getSides(Triangle tri){ //重载 return 3 ; } public int getSides(Rectangle rec){ //重载 return 4 ; } } class Triangle extends Shape { public int getSides() { //重写,实现多态 return 3; } } class Rectangle extends Shape { public int getSides(int i) { //重载 return i; } } 注意Triangle类的办法是重写,而Rectangle类的办法是重载.对两者比较,可以发现多态对重载的优点: 如果用重载,则在父类里要对应每一个子类都重载一个取得边数的办法; 假如用多态,则父类只提供取得边数的接口,至于取得哪个形状的边数,怎样取得,在子类里各自实现(重写).PHP教程 编程之家培训学院每天发布《PHP面向对象编程之深入理解方法重载与方法覆盖(多态)》等实战技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培养人才。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |