2013-05-21 37 views
8

Có cách nào để làm cho nó hoạt động không? Xem ví dụ:thay thế lớp trong php

class car { 
     function __construct($type){ 
       switch ($type) { 
         case 'big' : return new big_car(); 
         case 'small' : return new small_car(); 
       } 
     } 
     function whatisit() { 
       echo "this is car ;(\n"; 
     } 
} 

class big_car extends car { 
     function __construct(){} 
     function whatisit() { 
       echo "this is big car ;) \n"; 
     } 
} 

class small_car extends car { 
     function __construct(){} 
     function whatisit() { 
       echo "this is small car ;) \n"; 
     } 
} 

nên mục tiêu là để sử dụng nó theo cách này:

$mycar = new car('big'); 
$mycar->whatisit(); // i want it to say that it's big 

Tôi đoán rất nhiều mà cách xấu của nó và nó không thể làm việc theo cách này nhưng có lẽ đó là một thủ thuật?

PS :: Tôi biết tôi có thể sử dụng phương pháp tĩnh đặc biệt cho điều đó nhưng ...

+0

Constructors không thể trở về giá trị trong PHP; bạn sẽ cần một phương pháp khác. – NullUserException

+0

@kitty được upvoted cho nick + avatar của bạn. – moonwave99

+0

Bạn cần thêm giao diện "ô tô" và nhà máy "ô tô" - cố gắng làm cả hai cùng nhau là xấu và khó. – Xeoncross

Trả lời

9

Bạn cần nhà máy sản xuất ô tô để tạo ô tô mới; đây không phải là JavaScript :)

class car_factory 
{ 
    function create_car($type = null) 
    { 
     switch ($type) { 
      case 'big': 
       return new big_car(); 

      case 'small': 
       return new small_car(); 

      case null: 
       return new car(); 
     } 
     throw new InvalidArgumentException($type); 
    } 
} 

$factory = new car_factory; 
$small_car = $factory->create_car('small'); 
$std_car = $factory->create_car(); 

Tất nhiên, bạn nên xóa hàm __construct khỏi mã ban đầu của mình.

Như mentioned trong các ý kiến ​​bạn hoàn toàn có thể khái quát hóa điều này bằng cách sử dụng các lớp học năng động, giả sử phần mở rộng lớp có các nhà xây dựng và cùng lớp đặt tên phù hợp:

class car_factory 
{ 
    function create_car($type = null) 
    { 
     if (is_null($type)) { 
      return new car(); 
     } 

     $class = "{$type}_car"; 
     if (class_exists($class)) { 
      $obj = new $class(); 

      if ($obj instanceof car) { 
       return $obj; 
      } 
     } 

     throw new InvalidArgumentException($type); 
    } 
} 

Cá nhân tôi không có sở thích một trong hai cách; nếu khả năng mở rộng là một yếu tố quan trọng, hãy sử dụng nó, nếu không thì chỉ cần đơn giản là switch.

+0

Để hành xử theo cách anh ta muốn tôi tin rằng nó nên 'trả lại xe mới(); 'khi đối số không phải là' lớn' hoặc' nhỏ', thay vì ném một ngoại lệ. – Paulpro

+0

@Paulpro Điểm tốt :) được thêm vào. –

+0

Có vẻ tốt :) Chỉnh sửa đẹp. – Paulpro

1

[...] bạn hoàn toàn có thể khái quát hóa điều này bằng cách sử dụng các lớp học năng động, giả sử phần mở rộng lớp có các nhà xây dựng và cùng lớp đặt tên là phù hợp

Bạn có thể thêm linh hoạt hơn sử dụng Reflection:

class car_factory 
{ 
    function create_car($class = null, $constructorArgs = array()) 
    { 
     if (is_null($class)) { 
      return new car(); 
     } 

     try { 
      $refl = new ReflectionClass($class); 
      if (!$refl->isSubclassOf('car') { 
       throw new DomainException("Type: {$class} is not a car type"); 
      } 
      return $refl->newIntanceArgs($constructorArgs); 
     } catch(ReflectionException $e) { 
      throw new DomainException("Invalid car type: {$class}"); 
     } 
    } 
} 

Bây giờ sử dụng:

$factory = new car_factory(); 
$car1 = $factory->create_car('big_car'); 
$car2 = $factory->create_car('small_car'); 
$car3 = $factory->create_car('fancy_car_name_with_constructor_args', array("I'm fancy!")); 
+0

Ngoài ra, nếu bạn muốn chỉ cần vượt qua các đối tượng, bạn có thể bỏ qua các relfection và sử dụng 'type-hinting':' function __construct (\ Car $ car) {$ this-> car = $ car; } ' – Xeoncross

+0

Trong trường hợp này, bạn phải khởi tạo một đối tượng và chuyển nó đến nhà máy, vì vậy, nhà máy là gì? –

+0

Có, tôi đã không nói về trường hợp cụ thể này - chỉ cần đăng bài cho bất kỳ ai có thể đọc qua câu trả lời này. Nó thực sự DI thiết kế thay vì một mô hình nhà máy mà có vẻ là tốt hơn cho thử nghiệm anyway. – Xeoncross