ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## **多态** 多态是指在面向对象中能够根据使用类的上下文来重新定义或改变类的性质和行为 一个对外接口,多个内部实现方法 多态性的一般定义为:**同一个操作作用于不同的类的实例,将产生不同的执行结果**。即不同类的对象收到相同的消息时,将得到不同的结果。 在实际的应用开发中,采用面向对象中的多态主要在于可以**将不同的子类对象都当作一个父类来处理**,并且可以屏蔽不同子类对象之间所存在的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化 如例子2: 具有表现多种形态的能力特征。在面向对象中表示根据对象的类型以不同方式处理。多态性允许每个对象以适合自身的方式去响应共同的消息。多态性增强了软件的灵活性和重用性。 >[danger]多态一般用接口做最好 ``` <?php // 多态:多种形态 // 走路 // 坐公交 // 骑自行车 abstract class Style { // 上 abstract public function up(); // 下 abstract public function down(); } // 走路的方式(继承了Style,就必须实现up和down两个方法) class Walk extends Style { public function up() { echo '迈左腿走路<br>'; } public function down() { echo '迈右腿走路<br>'; } } // 坐公交的方式 class Bus extends Style { public function up() { echo '上车<br>'; } public function down() { echo '下车<br>'; } } // 自行车 class Bike extends Style { public function up() { echo '左腿蹬车<br>'; } public function down() { echo '右腿等车<br>'; } } ``` 获取来学校的方式(Style作为类型约束条件,约束必须传递的参数是其子类实例化的对象) ``` function getStyle(Style $obj) { /* if ($obj instanceof Walk) { $obj->leftTui(); $obj->rightTui(); } else if ($obj instanceof Bus) { $obj->up(); $obj->down(); } else if ($obj instanceof Bike) { $obj->leftDeng(); $obj->rightDeng(); }*/ $obj->up(); $obj->down(); } $w = new Walk; $b = new Bus; $bike = new Bike; getStyle($w); getStyle($b); getStyle($bike); ``` 获取来学校的方式(Style作为类型约束条件,约束必须传递的参数是其子类实例化的对象) ``` function getStyle(Style $obj) { $obj->up(); $obj->down(); } $w = new Walk; $b = new Bus; $bike = new Bike; getStyle($w); getStyle($b); getStyle($bike); ``` 例子2:多态的应用设计 >[danger]在实际的应用开发中,通常为了使项目能够在以后的时间里的轻松实现扩展与升级,需要通过继承实现可复用模块进行轻松升级。在进行可复用模块设计时,就需要尽可能的减少使用流程控制语句。此时就可以采用多态实现该类设计。 通常采用流程控制语句实现不同类的处理。其代码如下所示。 ``` class painter{ //定义油漆工类 public function paintbrush(){ //定义油漆工动作 echo "油漆工正在刷漆!/n"; } } class typist{ //定义打字员类 public function typed(){ //定义打字员工作 echo "打字员正在打字!/n"; } } function printworking($obj){ //定义处理类的函数 if($obj instanceof painter){ //若对象是油漆工类,则显示油漆工动作 $obj->paintbrush(); }elseif($obj instanceof typist){ //若对象是打字员类,则显示打字员动作 $obj->typed(); }else{ //若非以上类,则显示出错信息 echo "Error: 对象错误!"; } } printworking(new painter()); //显示员工工作 printworking(new typist()); //显示员工工作 ``` 分析:在上述程序中,首先定义两个员工类:油漆工类和打字员类。然后定义一个处理函数,在该函数中,判断员工是否为已经定义的员工,打印出员工的工作状态。其结果如下所示。 油漆工正在刷漆 打字员正在打字 从 以上程序可轻松看出,若想显示其几种员工的工作状态,需要首先定义该员工类,并在该员工类中定义员工的工作,然后在printworking()函数中增 加elseif语句以检查对象是哪一员工类的实例。这在实际的应用中,是非常不可取的。若此时采用多态,则可以轻松解决此问题。 可以首先创建一个员工父类,所有的员工类将继承自该员工父类,并且继承父类的所有方法与属性。然后在员工类中创建“是一”关系,判断是否为合法的员工。 【示例】例举了采用多态的方式改写上例。其代码如下所示。 */ //代码如下: ``` class employee{//定义员工父类 protected function working(){//定义员工工作,需要在子类的实现 echo "本方法需要在子类中重载!"; } } class painter extends employee{//定义油漆工类 public function working(){//实现继承的工作方法 echo "油漆工正在刷漆!/n"; } } class typist extends employee{//定义打字员类 public function working(){ echo "打字员正在打字!/n"; } } class manager extends employee{//定义经理类 public function working(){ echo "经理正在开会!"; } } function printworking($obj){//定义处理方法 if($obj instanceof employee){//若是员工对象,则显示其工作状态 $obj->working(); }else{//否则显示错误信息 echo "Error: 对象错误!"; } } printworking(new painter());//显示油漆工的工作 printworking(new typist());//显示打字员的工作 printworking(new manager());//显示经理的工作 ``` 分析:在上述程序中,首先定义一个员工基类,并定义一个员工工作状态的方法。然后定义将继承自员工基类的三个员工类:油漆工类、打字员类和经理类。然后定义显示员工工作状态的方法。并在该方法中创建一个“是一”关系,用于判断是否为合法的员工。其结果如下所示。 油漆工正在刷漆! 打字员正在打字! 经理正在开会! 从上例可发现,无论增加多少个员工类,只需要实现自员工父类继承的该员工类和方法。而无须修改显示员工工作状态的方法printworking()。 还有一只是改变参数数量的重载,同样是因为PHP也不支持方法的重载,所以也需要些变通的方法实现,如下: ``` // 通过可变参数来达到改变参数数量重载的目的 // 不是必须传入的参数,必须在函数定义时赋初始值 function open_database($DB, $cache_size_or_values=null, $cache_size=null) { switch (function_num_args()) // 通过function_num_args()函数计算传入参数的个数,根据个数来判断接下来的操作 { case 1: $r = select_db($DB); break; case 2: $r = select_db($DB, $cache_size_or_values); break; case 3: $r = select_db($DB, $cache_size_or_values, $cache_size); break; } return is_resource($r); } ``` 例子4: ``` <?php /** * 虚基类 */ abstract class T{ abstract function show(); } /** * 子类 */ class T1 extends T { public function show(){ echo "T1 from abstract class!<br/>"; } public function show1(){ echo "T1 not from abstract class!<br/>"; } } /** * 子类 */ class T2 extends T { public function show(){ echo "T2 from abstract class!<br/>"; } public function show1(){ echo "T2 not from abstract class!<br/>"; } } class T3 { public function show(){ echo "in T3!<br/>"; } public function show1(){ echo "in T3!<br/>"; } } $t1 = new T1(); $t2 = new T2(); $t3 = new T3(); show($t1); show($t2); //报错,$t3不是T,所以被show函数调用的时候,会报类型不对的错误 //show($t3); function show( T $t ){//注意参数的类型 $t->show(); $t->show1(); } ```