PHP示例中的通用多态性

PHP示例中的通用多态性,php,polymorphism,Php,Polymorphism,因为只有狗才能玩“取回”,这个例子是好主意还是坏主意?由于使用instanceof,我怀疑这是一个非常糟糕的主意,但我不完全确定原因 class Animal { var $name; function __construct($name) { $this->name = $name; } } class Dog extends Animal { function speak() { return "Woof, woof!"

因为只有狗才能玩“取回”,这个例子是好主意还是坏主意?由于使用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();
}

本质上我想问的是:“所有子类应该有相同的接口,还是可以有不同的接口?”

在本文中,讨论接口很有用

任何实现健谈界面的动物或人类(或外国人)都可以在需要健谈的环境中使用:

protected function makeItSpeak(Talkative $being) {
    echo $being->speak();
}
这是一种正确使用的多态方法。你不在乎你在处理什么,只要它能说话()

如果
Dog
s也可以玩fetch,那对他们来说是很好的。如果你想概括一下,也可以从接口的角度来考虑。也许有一天,你会得到一只训练有素的猫,它也会玩取回游戏

class Cog extends Cat implements Playfulness {
    public function playFetch() { ... }
}
这里最重要的一点是,当你对某个东西调用
playFetch()
时,这是因为你想和那个动物玩fetch。您不调用
playFetch
,因为。。。你可以,但因为你想在这一刻玩打球。如果你不想玩fetch,那就别叫它了。如果您需要在特定情况下玩fetch,那么您需要可以玩fetch的东西。您可以通过接口声明来确保这一点

使用类继承可以实现同样的效果,只是灵活性较差。在存在刚性层次结构的某些情况下,尽管它非常有用:

abstract class Animal { }

abstract class Pet extends Animal { }

class Dog extends Pet {
    public function playFetch() { ... }
}

class GermanShepherd extends Dog {
    public function beAwesome() { ... }
}
然后,在某些特定的上下文中,您可能不需要任何可以执行某些操作(接口)的对象,但您特别需要一个
GermanShepherd
,因为只有它才能令人敬畏:

protected function awesomeness(GermanShepherd $dog) {
    $dog->beAwesome();
}
也许在这条路上你会创造出一种新的
GermanShepherd
s,它也很棒,但是
extend
the
GermanShepherd
类。它们仍然可以使用
awesomeness
函数,就像使用接口一样


你当然不应该做的是循环一堆随机的事情,检查它们是什么,让它们做自己的事情。这在任何情况下都不太合理。

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);
?>


几乎和你一样,克里希纳达斯,布拉德。本文帮助我理解了如何在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);
?>

接口形状\u抽屉{
公共功能图(外形$obj);
}
类circle实现了shape\u抽屉{
公共功能图(外形$obj){
回显“绘图圆,区域:{$obj->Area}
”; } } 类square实现了形状_抽屉{ 公共功能图(外形$obj){ echo“绘图方块,面积:{$obj->Area}
”; } } 类triangle实现了shape\u抽屉{ 公共功能图(外形$obj){ echo“绘制三角形,区域:{$obj->Area}
”; } } 一流的造型工厂{ 公共静态函数getShape(){ $shape=$_请求['shape']; 如果(类_存在($shape)){ 返回新的$shape(); } 抛出新异常(“不支持的格式”); } } 阶级形态{ 公共功能建筑(面积){ $this->area=$area; } 公共功能图(外形图$obj){ 返回$obj->draw($this); } } $shape=新形状(50); 试一试{ $drawer=shape_工厂::getShape(); } 捕获(例外$e){ $drawer=新圆(); } echo$shape->draw($drawer);
我很确定以前有人问过这个问题,但简单的回答是子类可以有不同的接口。我很确定第一个示例不正确,因为使用instanceof进行条件逻辑。多态性的全部目的不是为了不这样做吗?为什么你想让所有的动物都做些什么(说话),除了一种动物(狗)?听起来好像是错误的逻辑在循环中,而不是类定义。它们都在说话,包括狗。但是只有狗才能玩。不管怎样,我想我可能已经在这里找到了一些有用的东西:如果两个不同的对象可以用不同的方式做相同的事情,那就是多态性。如果一个对象还可以做其他事情,那么就这样吧。那不是多态行为,因为它是对象特有的行为。你就不会把那个特定的行为当作多态的。看到一个php开发人员谈论接口是令人耳目一新的。我在php中经常使用它们,但在大多数主要框架中都没有爱,因此普通php开发人员很少采用这种思想。@deceze回答得很好。但我想知道这些特征是否也值得在这里提及@Muhammad不是真的,依我看。特征不可识别,因此与讨论无关。我知道它很古老,但如果我的狗能“呼吸”、“行走”、“跳跃”,我的猫也能,这是否意味着我必须实现所有这些接口?那是很多工具,不是吗@Steve 1)实际上,您可能不会为这些方法中的每一个创建一个接口,而是创建一个接口,将所有三个方法定义在一起。这取决于您将接口细分为有意义的部分,既不太详细,也不太大和不相关。2) 您可以创建复合接口,例如,
接口哺乳动物扩展呼吸、行走、跳跃
    <?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);
?>
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);