带有 PHP 示例的一般多态性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8542661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 04:57:29  来源:igfitidea点击:

General Polymorphism with PHP examples

phppolymorphism

提问by Dan

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.

由于只有 Dogs 可以玩“fetch”,这个例子是好还是坏主意?由于 instanceof 的使用,我怀疑这是一个非常糟糕的主意,但我不完全确定为什么。

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 areboth Data Objects so it's very confusing.

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

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 thinkI'm asking is: "should all subclasses have the same interface or can they have different ones?"

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

回答by deceze

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:

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

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

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

这是一种正确使用的多态方法。你不在乎你在处理什么,只要它可以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.

如果Dogs 也可以玩 fetch,那对他们来说很棒。如果你想概括这一点,也可以从接口的角度考虑。也许有一天你会得到一只训练有素的猫,它也会玩接球游戏。

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

The important point here being that when you callplayFetch()on something, it's because you want to play fetch with that animal. You don't call playFetchbecause, 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.

重要的一点是,当你呼唤playFetch()某物时,那是因为你想和那只动物玩捉迷藏。你不打电话playFetch是因为,好吧……你可以,但因为你想在这一刻玩取球。如果你不想玩 fetch,那么你就不要调用它。如果你在某种情况下需要玩 fetch,那么你需要一些可以玩 fetch 的东西。您可以通过接口声明来确保这一点。

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 objectthat can do something (interface), but you are specifically looking for a GermanShepherd, because only it can be awesome:

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

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

Maybe down the road you'll make a new breed of GermanShepherds that are also awesome, but extendthe GermanShepherdclass. They'll still work with the awesomenessfunction, just like with interfaces.

也许在路上你会是一个新品种的GermanShepherdS中的还真棒,但extendGermanShepherd类。他们仍然会使用该awesomeness函数,就像使用接口一样。

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.

你当然不应该做的是遍历一堆随机的东西,检查它们是什么并让它们做自己的事情。这在任何情况下都不是很明智。

回答by Krishnadas PC

Another example for Polymorphism in PHP

PHP 多态的另一个例子

    <?php
interface Shape {
   public function getArea();
}

class Square implements Shape {
   private $width;
   private $height;

   public function __construct($width, $height) {
      $this->width = $width;
      $this->height = $height;
   }

   public function getArea(){
      return $this->width * $this->height;
   }
}

class Circle implements Shape {
   private $radius;

   public function __construct($radius) {
      $this->radius = $radius;
   }

   public function getArea(){

      return 3.14 * $this->radius * $this->radius;
   }
}

function calculateArea(Shape $shape) {
   return $shape->getArea();
}

$square = new Square(5, 5);
$circle = new Circle(7);

echo calculateArea($square), "<br/>";
echo calculateArea($circle);
?>

回答by Ahad Ali

Almost the same as you Krishnadas, Brad. This article helped me alot in understanding how to handle polymorphism in PHP

几乎和你克里希那达一样,布拉德。这篇文章帮助我理解了如何处理 PHP 中的多态性

http://code.tutsplus.com/tutorials/understanding-and-applying-polymorphism-in-php--net-14362

http://code.tutsplus.com/tutorials/understanding-and-applying-polymorphism-in-php--net-14362

interface shape_drawer{
    public function draw(Shape $obj);
}

class circle implements shape_drawer{
    public function draw(Shape $obj){
        echo "Drawing Circle, Area: {$obj->area} <br>";
    }
}

class square implements shape_drawer{
    public function draw(Shape $obj){
        echo "Drawing Square, Area: {$obj->area} <br>";
    }
}

class triangle implements shape_drawer{
    public function draw(Shape $obj){
        echo "Drawing Triangle, Area: {$obj->area} <br>";
    }    
}

class shape_factory{
    public static function getShape(){

        $shape = $_REQUEST['shape'];

        if(class_exists($shape)) {
            return new $shape();
        }
        throw new Exception('Unsupported format');
    }
}

class Shape{

    public function __construct($area){
        $this->area = $area;
    }
    public function draw(shape_drawer $obj) {
        return $obj->draw($this);
    }
}


$shape = new Shape(50);
try {
    $drawer = shape_factory::getShape();
}
catch (Exception $e) {
    $drawer = new circle();
}

echo $shape->draw($drawer);