热搜:NVER node 开发 php

PHP中关于多态的疑问

2024-09-07 13:45:01
PHP中关于多态的疑问

维基百科中关于多态有一个定义: 在面向对象语言中,接口的多种不同的实现方式即为多态

请看此文:
http://www.cnblogs.com/tecs27/archive/2012/03/13/2394028.html

文中给出了两个代码示例,其中用流程控制的代码段如下

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());                     //显示员工工作



为了展示多态,下文又给出使用多态的代码段:
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());//显示经理的工作


后一个代码是统一了不同子类之间的方法名来实现多态,这是否是个多态的正确示例呢?如果是的,那么是否可以理解为,继承某个抽象类的所有子类相对于抽象父类来说都是多态的?


另外在论坛的另一个讨论贴中(http://bbs.csdn.net/topics/390025104),55L的xuzuning老师给出了一个代码示例:
class Animal {  var $voice = '未定义';  var $root;  function __construct() {    $this->root = $this;  }  function signal($o) {    $this->root = $o;  }  function Talk() {    echo $this->root->voice;  }} class Cat extends Animal {  var $voice = '喵';} class Dog extends Animal {  var $voice = '汪汪';} $a = new Animal;  $a->Talk();    $a->signal(new Cat);$a->Talk(); $a->signal(new Dog);$a->Talk();


这段代码中的变量$a最先声明为Animal父类的示例,所以输出是“未定义”,之后又声明为子类Cat和Dog,那么声明Cat时变量$a指向到Cat的实例上去了,所以调用$a->talk()实际上就是调用Cat的talk。同理,$a声明为Dog的实例时又把cat对象覆盖掉了。xuzuning老师在帖中说 父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作,但这段代码看不出$a调用talk方法是经过父类这一步的,而是新的对象覆盖了前一个对象,调用的完全是新对象的方法。那么xuzuning老师的这个代码示例是否是不恰当的呢?


最近一直对多态的具体实践迷惑不解,有的文章中提到需要强制类型定义,有的在示例代码中用到了 instanceof关键字来判断是否继承于某个类。哪位老师能给出一个清晰的定义及代码示例并解答上述代码示例是否是多态的实践呢?


回复讨论(解决方案)

例子都行, 第一个更典型, 父类里最好是虚函数以确保子类实现.

多态的关键是 "相同的接口", "不同的实现", 别的细节不要纠结....

例子都行, 第一个更典型, 父类里最好是虚函数以确保子类实现.

多态的关键是 "相同的接口", "不同的实现", 别的细节不要纠结....

多谢helloyou0老师,PHP中有虚函数吗?

php里应该说抽象函数...
http://www.php.net/manual/en/language.oop5.abstract.php

悟性 悟性 悟性....

这有点像佛经里的东西 看你怎么悟 概念就抽象 用抽象的方法来描述抽象具体行为...嘿嘿

但这段代码看不出$a调用talk方法是经过父类这一步的,而是新的对象覆盖了前一个对象,调用的完全是新对象的方法。 你 print_r($a); 一下就知道谁是谁了

php里应该说抽象函数...
http://www.php.net/manual/en/language.oop5.abstract.php

虚函数有人说是静态延迟绑定,我看比较像。抽象函数为什么能保证子类的实现呢?

引用 楼主 chenlong451 的回复:但这段代码看不出$a调用talk方法是经过父类这一步的,而是新的对象覆盖了前一个对象,调用的完全是新对象的方法。你 print_r($a); 一下就知道谁是谁了

xuzuning老师来了,非常感谢你的提示。

print_r后的结果是

Animal Object ( [voice] => 未定义 [root] => Dog Object ( [voice] => 汪汪 [root] => Dog Object *RECURSION* ) )

竟然变成对象数组了,并且保留了父类中的voice静态属性。这是怎么回事呢?为什么不是覆盖呢?

为什么是覆盖呢?
说说你的理由

为什么是覆盖呢?
说说你的理由

明白了,阅读代码不仔细。惭愧。