带有 PHP 示例的通用多态性 [英] General Polymorphism with PHP examples

查看:28
本文介绍了带有 PHP 示例的通用多态性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为只有 Dogs 才能玩fetch",所以这个例子是好主意还是坏主意?由于使用了 instanceof,我怀疑这是一个非常糟糕的主意,但我不完全确定为什么.

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

另一个例子.由于我不断创建具有 ID 的数据对象,我想我不妨从基类中扩展它们以避免代码重复.再说一次,这很糟糕,对吧?因为椅子没有名字,狗没有轮子.但它们都是都是数据对象,所以很混乱.

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

基本上我认为我要问的是:所有子类应该具有相同的接口还是可以有不同的接口?"

推荐答案

在这种情况下,谈论接口很有用.

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

实现 Talkative 接口的任何动物或人类(或外星人)都可以在需要健谈生物的环境中使用:

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

这是一种正确使用的多态方法.你不在乎在处理什么,只要它可以speak().

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

如果 Dog 也可以玩 fetch,那对他们来说非常棒.如果你想概括这一点,也可以从接口的角度来考虑.也许有一天你会得到一只训练有素的猫,它也会玩捉.

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() { ... }
}

这里重要的一点是,当您调用 playFetch() 时,是因为您想与该动物一起玩fetch.你不调用 playFetch 是因为,嗯……你可以,但是因为你想在这个时刻播放 fetch.如果您不想玩 fetch,那么您就不要调用它.如果你需要在某种情况下玩 fetch,那么你需要一些可以玩 fetch 的东西.您可以通过接口声明来确保这一点.

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() { ... }
}

然后,在某些特定的上下文中,您可能不需要 任何可以做某事(接口)的对象,但您正在专门寻找一个 GermanShepherd,因为只有它可能很棒:

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

也许你会在路上制作出一种新的GermanShepherd,它们也很棒,但是extend GermanShepherd 类.他们仍然可以使用 awesomeness 函数,就像使用接口一样.

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.

这篇关于带有 PHP 示例的通用多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆