2011-12-17 32 views
25

Vì chỉ có Chó mới có thể chơi "tìm nạp", ví dụ này là một ý tưởng hay hay? Tôi nghi ngờ đó là một ý tưởng thực sự tồi do việc sử dụng instanceof, nhưng tôi không hoàn toàn chắc chắn lý do tại sao.Tính đa hình chung với các ví dụ PHP

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

Ví dụ khác. Khi tôi liên tục tạo các đối tượng dữ liệu có ID, tôi đã tìm ra rằng tôi có thể mở rộng tất cả chúng từ một lớp cơ sở để tránh trùng lặp mã. Một lần nữa, điều này là xấu phải không? Như một chiếc ghế không có tên và một con chó không có bánh xe. Nhưng chúng cả hai đối tượng dữ liệu nên rất khó hiểu.

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

Về cơ bản những gì tôi nghĩ tôi hỏi là: "nên tất cả các lớp con có cùng một giao diện hoặc họ có thể có những người khác nhau?"

+2

Khá chắc chắn điều này đã được yêu cầu ở đây trước, nhưng câu trả lời ngắn gọn là nó bật đèn xanh cho các lớp con để có một giao diện khác nhau. – NullUserException

+0

Tôi khá chắc chắn ví dụ đầu tiên là không đúng do việc sử dụng instanceof cho logic điều kiện. Không phải toàn bộ điểm của Đa hình không làm điều này sao? – Dan

+0

Tại sao bạn muốn để có được tất cả các loài động vật để làm một cái gì đó (nói chuyện), ngoại trừ một loại (Dog)? Âm thanh như logic bị lỗi nằm trong vòng lặp, không phải là định nghĩa lớp. – NullUserException

Trả lời

44

Trong ngữ cảnh này, hữu ích khi nói về các giao diện .

interface Talkative { 
    public function speak(); 
} 

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

Bất kỳ động vật hoặc nhân (hoặc người nước ngoài) mà thực hiện giao diện Talkative có thể được sử dụng trong một bối cảnh mà con nói nhiều là cần thiết:

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

Đây là một phương pháp đa hình sử dụng đúng cách. Bạn không quan tâm những gì bạn đang xử lý miễn là nó có thể speak().

Nếu Dog s cũng có thể phát tìm nạp, điều đó thật tuyệt vời cho chúng. Nếu bạn muốn khái quát hóa điều đó, hãy suy nghĩ về nó về mặt giao diện. Có lẽ một ngày nào đó bạn sẽ nhận được một con mèo được đào tạo cao có thể chơi được.

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

Điểm quan trọng ở đây là khi bạn gọiplayFetch() trên một cái gì đó, đó là vì bạn muốn chơi lấy với con vật đó. Bạn không gọi playFetch bởi vì, tốt ... bạn có thể, nhưng bởi vì bạn muốn chơi tìm nạp trong thời điểm này rất. Nếu bạn không muốn chơi lấy, sau đó bạn không gọi nó. Nếu bạn cần phải tìm nạp trong một tình huống nhất định, sau đó bạn cần một cái gì đó mà có thể chơi lấy. Bạn đảm bảo điều này thông qua các khai báo giao diện.

Bạn có thể đạt được điều tương tự bằng cách sử dụng kế thừa lớp, nó chỉ kém linh hoạt hơn. Trong một số tình huống mà phân cấp cứng nhắc tồn tại mặc dù nó hoàn toàn hữu ích:

abstract class Animal { } 

abstract class Pet extends Animal { } 

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

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

Sau đó, trong một số bối cảnh cụ thể, bạn có thể không cần bất kỳ đối tượng có thể làm điều gì đó (giao diện), nhưng bạn đang tìm kiếm đặc biệt cho một GermanShepherd , bởi vì chỉ có nó có thể là tuyệt vời:

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

lẽ xuống đường bạn sẽ tạo ra một giống mới của GermanShepherd s mà cũng rất tuyệt vời, nhưng extend lớp GermanShepherd. Chúng vẫn hoạt động với chức năng awesomeness, giống như với các giao diện.

Điều bạn chắc chắn không nên làm là lặp qua một loạt các điều ngẫu nhiên, kiểm tra xem chúng là gì và làm cho chúng làm việc riêng của chúng.Đó không phải là rất hợp lý trong mọi ngữ cảnh.

+5

làm mới để xem nhà phát triển php nói về giao diện. tôi sử dụng chúng rất nhiều trong php, nhưng trong hầu hết các khuôn khổ chính không có tình yêu, và do đó rất thấp chấp nhận ý thức hệ của nhà phát triển php phổ biến. –

+0

@deceze Câu trả lời tuyệt vời.Nhưng tôi tự hỏi, nếu các đặc điểm cũng đáng nhắc đến ở đây. http://www.php.net/manual/en/language.oop5.traits.php –

+0

@Muhammad Không thực sự, IMO. Các đặc điểm không phải là loại có thể gợi ý và do đó có phần không liên quan đến cuộc thảo luận. – deceze

22

Một ví dụ khác cho Polymorphism trong 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); 
?> 
2

Gần giống như bạn Krishnadas, Brad. Bài viết này đã giúp tôi rất nhiều trong việc tìm hiểu làm thế nào để xử lý đa hình trong 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); 
Các vấn đề liên quan