doucan1996 2011-12-17 04:49
浏览 64
已采纳

一般多态性与PHP的例子

As only Dogs can play "fetch", is this example a good or a bad idea? I suspect it's a really bad idea due to the usage of instanceof, but I'm not entirely sure why.

class Animal {
    var $name;
    function __construct($name) {
        $this->name = $name;
    }
}

class Dog extends Animal {
    function speak() {
        return "Woof, woof!";
    }

    function playFetch() {
        return 'getting the stick';
    }
}

class Cat extends Animal {
    function speak() {
        return "Meow...";
    }
}

$animals = array(new Dog('Skip'), new Cat('Snowball'));

foreach($animals as $animal) {
    print $animal->name . " says: " . $animal->speak() . '<br>';
    if ($animal instanceof Dog) echo $animal->playFetch();
}

Another example. As I am constantly creating data objects that have an ID, I figured I might as well extend them all from a base class to avoid code duplication. Again, this was bad right? As a Chair doesn't have a name and a Dog doesn't have wheels. But they are both Data Objects so it's very confusing.

class Data_Object {
    protected $_id;

    function setId($id) {
        $this->_id = $id;
    }

    function getId() {
        return $this->_id;
    }
}

class Dog extends Data_Object {
    protected $_name;
    function setName($name) {
        $this->_name = 
    }

    function getName() {
        return $this->_name;
    }
}

class Chair extends Data_Object {
    protected $_numberOfWheels;
    function setNumberOfWheels($number) {
        $this->_numberOfWheels = $number;
    }

    function getNumberOfWheels() {
        return $this->_numberOfWheels;
    }
}

Essentially what I think I'm asking is: "should all subclasses have the same interface or can they have different ones?"

  • 写回答

3条回答 默认 最新

  • doudun1934 2011-12-17 05:47
    关注

    In this context it's useful to talk about interfaces.

    interface Talkative {
        public function speak();
    }
    
    class Dog extends Animal implements Talkative {
        public function speak() {
            return "Woof, woof!";
        }
    }
    

    Any animal or human (or alien) that implements the Talkative interface can be used in a context where talkative beings are needed:

    protected function makeItSpeak(Talkative $being) {
        echo $being->speak();
    }
    

    This is a properly used polymorphic method. You don't care what you're dealing with as long as it can speak().

    If Dogs can also play fetch, that's great for them. If you want to generalize that, think about it in terms of an interface as well. Maybe one day you'll get a highly trained cat which can play fetch as well.

    class Cog extends Cat implements Playfulness {
        public function playFetch() { ... }
    }
    

    The important point here being that when you call playFetch() on something, it's because you want to play fetch with that animal. You don't call playFetch because, well... you can, but because you want to play fetch in this very moment. If you don't want to play fetch, then you don't call it. If you need to play fetch in a certain situation, then you need something that can play fetch. You ensure this through interface declarations.

    You can achieve the same thing using class inheritance, it's just less flexible. In some situations where rigid hierarchies exist though it's perfectly useful:

    abstract class Animal { }
    
    abstract class Pet extends Animal { }
    
    class Dog extends Pet {
        public function playFetch() { ... }
    }
    
    class GermanShepherd extends Dog {
        public function beAwesome() { ... }
    }
    

    Then, in some specific context, you may not require any object that can do something (interface), but you are specifically looking for a GermanShepherd, because only it can be awesome:

    protected function awesomeness(GermanShepherd $dog) {
        $dog->beAwesome();
    }
    

    Maybe down the road you'll make a new breed of GermanShepherds that are also awesome, but extend the GermanShepherd class. They'll still work with the awesomeness function, just like with interfaces.

    What you certainly should not do is to loop through a bunch of random things, check what they are and make them do their own thing. That's just not very sensible in any context.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码