it-swarm-pt.tech

Polimorfismo Geral com PHP exemplos

Como só os cães podem jogar "buscar", este exemplo é uma boa ou má ideia? Eu suspeito que é uma péssima idéia devido ao uso do instanceof, mas não tenho certeza do porquê.

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

Outro exemplo. Como estou constantemente criando objetos de dados que possuem um ID, imaginei que poderia estendê-los a partir de uma classe base para evitar a duplicação de código. Mais uma vez, isso foi ruim né? Como uma cadeira não tem nome e um cachorro não tem rodas. Mas eles são ambos os objetos de dados, por isso é muito confuso.

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

Essencialmente o que eu acho estou perguntando é: "todas as subclasses devem ter a mesma interface ou podem ter diferentes?"

26
Dan

Neste contexto, é útil falar sobre interfaces .

interface Talkative {
    public function speak();
}

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

Qualquer animal ou humano (ou alienígena) que implemente a interface Talkative pode ser usado em um contexto onde os seres falantes são necessários:

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

Este é um método polimórfico usado corretamente. Você não se importa o que você está lidando com o tempo que pode speak().

Se Dogs também pode reproduzir, isso é ótimo para eles. Se você quiser generalizar isso, pense também em termos de interface. Talvez um dia você receba um gato altamente treinado, que também pode jogar.

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

O ponto importante aqui é que quando você chama playFetch() em algo, é porque você quer jogar com esse animal. Você não chama playFetch porque, bem ... você pode, mas porque você quer jogar neste exato momento. Se você não quer jogar, então você não liga. Se você precisa jogar buscar em uma determinada situação, então você precisa de algo que possa reproduzir. Você garante isso através de declarações de interface.

Você pode conseguir a mesma coisa usando herança de classe, é menos flexível. Em algumas situações em que existem hierarquias rígidas, é perfeitamente útil:

abstract class Animal { }

abstract class Pet extends Animal { }

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

class GermanShepherd extends Dog {
    public function beAwesome() { ... }
}

Então, em algum contexto específico, você pode não exigir qualquer objeto que pode fazer alguma coisa (interface), mas você está especificamente procurando por uma GermanShepherd, porque somente ela pode ser incrível:

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

Talvez no futuro você faça uma nova geração de GermanShepherds que também sejam impressionantes, mas extend a classe GermanShepherd. Eles ainda funcionam com a função awesomeness, assim como nas interfaces.

O que você certamente não deve fazer é percorrer um monte de coisas aleatórias, verificar o que elas são e fazê-las fazer suas próprias coisas. Isso não é muito sensato em qualquer contexto.

48
deceze

Outro exemplo de polimorfismo em 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);
?>
26
Krishnadas PC

Quase o mesmo que você Krishnadas, Brad. Este artigo me ajudou muito a entender como lidar com o polimorfismo no 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

O polimorfismo descreve um padrão na programação orientada a objetos na qual as classes têm diferentes funcionalidades enquanto compartilham uma interface comum

Interface Uma interface é semelhante a uma classe, exceto que não pode conter código. Uma interface pode definir nomes e argumentos de métodos, mas não o conteúdo dos métodos. Qualquer classe que implemente uma interface deve implementar todos os métodos definidos pela interface. Uma classe pode implementar várias interfaces.

Uma interface é declarada usando a palavra-chave 'interface':

interface MyInterface {
    // methods
}

e é anexado a uma classe usando a palavra-chave 'implementa' (várias interfaces podem ser implementadas listando-as separadas por vírgulas):

class MyClass implements MyInterface {
    // methods
}

Os métodos podem ser definidos na interface como em uma classe, exceto sem o corpo a parte entre as chaves:

interface MyInterface {
    public function doThis();
    public function doThat();
    public function setName($name);
}

Todos os métodos definidos aqui precisarão ser incluídos em qualquer classe de implementação exatamente como descrito. (leia os comentários do código abaixo)

// VALID

class MyClass implements MyInterface {
    protected $name;
    public function doThis() {
        // code that does this
    }
    public function doThat() {
        // code that does that
    }
    public function setName($name) {
        $this->name = $name;
    }
}

// INVALID
class MyClass implements MyInterface {
    // missing doThis()!

    private function doThat() {
        // this should be public!
    }
    public function setName() {
        // missing the name argument!
    }
}
0
Saimon Anam