web-dev-qa-db-ja.com

PHPの例による一般的な多態性

犬だけが「フェッチ」をプレイできるので、この例は良いアイデアですか、悪いアイデアですか? 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();
}

もう一つの例。 IDを持つデータオブジェクトを常に作成しているので、コードの重複を避けるために、すべてを基本クラスから拡張することも考えました。繰り返しますが、これは悪いことでしたね?椅子には名前がなく、犬には車輪がありません。しかし、それらはare両方のデータオブジェクトなので、非常に混乱しています。

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

本質的に私はと思う私は尋ねています:「すべてのサブクラスは同じインターフェースを持つべきですか、異なるインターフェースを持つことができますか?」 =

27
Dan

このコンテキストでは、interfacesについて話すのが便利です。

_interface Talkative {
    public function speak();
}

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

おしゃべりなインターフェイスが実装されている動物または人間(またはエイリアン)は、おしゃべりな存在が必要な状況で使用できます。

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

これは、適切に使用される多態的な方法です。あなたは気にしませんwhatspeak()ができる限りあなたは対処しています。

Dogsもフェッチを再生できる場合、それは彼らにとって素晴らしいことです。それを一般化したい場合は、インターフェースの観点からも考えてください。たぶん、いつかフェッチをプレイできる高度に訓練された猫を手に入れるかもしれません。

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

ここで重要なのは、何かをcallplayFetch()するとき、その動物でフェッチをプレイしたいからです。 playFetchを呼び出さないのは、そうすることができるからです。しかし、この瞬間にフェッチをプレイしたいからです。フェッチを再生したくない場合は、呼び出しません。特定の状況でフェッチを再生する必要がある場合は、フェッチを再生できるものが必要です。これは、インターフェイス宣言を介して確認します。

クラスの継承を使用して同じことを実現できますが、柔軟性は劣ります。厳密な階層が存在するいくつかの状況では、完全に便利ですが、

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

たぶん、あなたは新しい種類のGermanShepherdsを作成するでしょう。これも素晴らしいですが、extendGermanShepherdクラスです。インターフェイスと同様に、awesomeness関数でも引き続き機能します。

確かにすべきではないことは、ランダムなものの束をループし、それらが何であるかを確認し、それらに独自のことをさせることです。それはどんな状況でもあまり賢明ではありません。

49
deceze

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);
?>
27
Krishnadas PC

ブラッド、クリシュナダスとほぼ同じ。この記事は、PHPでポリモーフィズムを処理する方法をよく理解するのに役立ちました。

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);
2
Ahad Ali