2013-06-10 40 views
5

Tôi đang gặp một số sự cố với Thừa kế PHP. Đây là thỏa thuận:PHP đơn và thừa kế

Tôi có lớp cơ sở này, Singleton:

namespace My_Namespace; 

abstract class Singleton { 
    protected static $instance = null; 

    static function get() { 
     if (null == static::$instance) { 
      static::$instance = new static; 
     } 
     return static::$instance; 
    } 

    private function __construct() { 

    } 
} 

tôi có một loạt các lớp kế thừa mà lớp Singleton, gọi họ là A, B, C, D. Một trong số họ trông giống như sau:

namespace My_Namespace; 

class A extends Singleton { 

    protected function __construct() { 

     B::get(); 

     if (some_condition()) { 
      C::get(); 
     } 
     else { 
      D::get(); 
     } 
    } 
} 

Bây giờ, tôi chỉ cần thực hiện một số A::get() để làm cho tất cả đều lăn. Các nhà xây dựng của A được gọi là, như mong đợi. Sau đó, hàm tạo của B được gọi, một lần nữa mà không có vấn đề gì. Bây giờ nó trở nên kỳ lạ. Sau khi được gọi là C::get(), nó nhận ra static::$instance như đã là một đối tượng của lớp B và không khởi tạo C chút nào. Tôi biết nếu tôi kết nối chúng, đó là __construct của B gọi C::get hoặc D::get nó hoạt động nhưng đó không phải là tối ưu cho mục đích của tôi. Đó có phải là do họ ở trong cùng phạm vi không? Nếu vậy, có cách nào xung quanh điều này không? Tôi hỏi điều này nhiều hơn sự tò mò hơn là mục đích thực tế - tôi biết tôi có thể dễ dàng thực hiện mô hình đơn trong mỗi người trong số họ. Vì vậy, bất kỳ ý tưởng? Cảm ơn!

P.S. Xin vui lòng không có 'đơn độc ác và bạn nên ghi trong ý kiến ​​địa ngục'. Tôi biết điều đó một cách hoàn hảo.

+1

+1 cho 'không ... ghi trong ý kiến ​​địa ngục' – phpisuber01

+1

Tôi tin rằng các lớp thừa kế cần một thuộc tính tĩnh cho thể hiện được chèn vào ... vì vậy hãy thêm 'protected static $ instance = null;' vào các lớp con . – Orangepill

+0

@Orangepill bạn đã nhận được. Tôi đã thêm dòng đó và tất cả đều hoạt động như mong đợi. “NHƯNG:” Điều đó làm cho toàn bộ lớp Singleton và những thứ thừa kế vô ích mặc dù ... Ý tưởng là có một chức năng đơn lẻ được đính kèm trong lớp đó. Liệu có thể không? –

Trả lời

2

Lưu ý rằng static::$instance = new static gọi hàm tạo (trong trường hợp của bạn) A.

Với giải pháp của bạn, bạn sẽ cần một thuộc tính tĩnh cho cá thể của bạn trong các lớp con của bạn.

Chỉ cần thêm

protected static $instance = null; 

đối với họ, và nó sẽ hoạt động tốt.

+0

Tại sao nó làm việc trong hai lần đầu tiên? Làm thế nào nếu tôi không ở trong cùng một phạm vi, như trong 'A :: get()' và 'B :: get()' nó tạo ra các cá thể thích hợp nhưng ngay sau khi nó chạm vào 'C :: get()' nó rơi trở lại cái mà nó dùng cho 'B :: get'? Điều đó có nghĩa gì không? –

+1

Nó không hoạt động trong hai lần đầu tiên, nó hoạt động lần đầu tiên, bạn gọi hàm 'A :: get()', sau đó hàm tạo của 'A' được gọi, gọi là' B :: get() ', so với' $ instance' từ lớp cơ sở ** * được thiết lập (lần đầu tiên nó được thiết lập) Và bây giờ bạn muốn gọi 'C :: get()', kiểm tra 'null == static :: $ instance', nhưng bây giờ là' $ instance' ** (từ lớp A) ** đã là một đối tượng. – bpoiss

+0

Hãy cho tôi một thời gian để nhận ra sự giải thích dễ dàng như thế nào. Tại đó 'static :: $ instance = new static', hàm tạo được gọi là hàm khởi tạo khác, tất cả trước khi gán bất cứ thứ gì cho biến $ instance thực tế vì nó chưa trả về. Tôi ngớ ngẩn quá. Cảm ơn câu trả lời. –

1

Khi giao dịch với các thuộc tính tĩnh nếu bạn muốn tính tĩnh các lớp kế thừa của khác với các lớp cơ sở bạn phải cung cấp một ngôi nhà cho nó sống.

Để giải quyết vấn đề chỉ xác định

protected static $instance = null; 

trên lớp học có nguồn gốc của bạn. Nếu không, nó sẽ sử dụng thuộc tính của lớp cơ sở.