2009-08-14 45 views
17

Tôi đã đấu tranh trong khu vực này trong nhiều ngày, và tôi đã đi đến kết luận, nhưng vì kết luận không phải là thứ tôi đang tìm kiếm, trước khi tôi từ bỏ, tôi sẽ cố gắng xem những người khác nói. Đức tin chết cuối cùng ...Mở rộng các lớp tĩnh PHP

Giả sử chúng ta có một siêu lớp (được gọi là "Siêu") và một lớp con (được gọi là "Phụ").

class Super { 
    protected static $title = 'super'; 
    public static function get_class_name()   
    { 
     echo __CLASS__; 
    } 
    public static function get_title() 
    { 
     echo self::$title; 
    } 
} 
class Sub extends Super { 
    protected static $title = 'sub'; 
} 

Bây giờ, có lẽ bạn sẽ thừa kế tất cả các phương thức của Super, tuy nhiên, dường như chỉ nhận được tham chiếu đến phương thức của Phụ.

Tôi nói điều này bởi vì nếu tôi gọi:

Sub::get_class_name(); 

đầu ra là "Super", và không phải là "con".

Và nếu tôi gọi:

Sub::get_title(); 

một lần nữa, kết quả là "siêu", và tôi thậm chí có tiêu đề $ khai báo trong Sub. Vì vậy, điều này có nghĩa là khi tôi gọi một hàm tĩnh kế thừa, phạm vi của hàm sẽ là lớp siêu, không phải là lớp được gọi (ngay cả khi bạn in backtrace, nó sẽ chỉ ra rằng cuộc gọi được thực hiện trên lớp cha! !!), và để có được phạm vi như lớp con mà cuộc gọi đang được thực hiện, tôi cần phải redeclare phương thức đó bên trong lớp con đó. Loại này đánh bại mục đích mở rộng lớp học, phải không?

Vì vậy, câu hỏi của tôi là, tôi có thể mở rộng một lớp tĩnh, gọi một trong các phương thức kế thừa và có phạm vi của lớp con không? hoặc ít nhất để có thể xác định tên lớp của nó? Và nếu không, tại sao tôi lại muốn mở rộng các lớp tĩnh?

Cảm ơn!

Trả lời

28

Một lần nữa, điều này là không thể trước PHP 5.3.0.

Late Static Binding được giới thiệu trong PHP 5.3.0 và cho phép bạn thực hiện chính xác những gì bạn muốn thông qua từ khóa static.

class Super { 
    protected static $title = 'super'; 
    public static function get_class_name()   
    { 
     echo __CLASS__; 
    } 
    public static function get_title() 
    { 
     echo static::$title; 
    } 
} 
class Sub extends Super { 
    protected static $title = 'sub'; 
} 

get_class_name() vẫn sẽ trở lại Super dù có __CLASS__ luôn trả về lớp hiện nay phương pháp được chạy được khai báo trong (loại giống như __FILE__ mà luôn luôn trả về tập tin hiện tại không có vấn đề nếu bạn đã bao gồm nó hay không).

Đối với điều đó bạn không có bất kỳ lựa chọn nào khác ngoài việc khai báo lại hàm trong lớp Sub.

class Super { 
    protected static $title = 'super'; 
    public static function get_class_name()   
    { 
     echo __CLASS__; 
    } 
    public static function get_title() 
    { 
     echo static::$title; 
    } 
} 
class Sub extends Super { 
    protected static $title = 'sub'; 

    public static function get_class_name()   
    { 
     echo __CLASS__; 
    } 
} 
+0

OK, giờ tôi đã hiểu. – treznik

3

Bạn có thể sử dụng get_called_class() để nhận tên lớp của lớp bạn đang gọi, ngay cả khi lớp đó tĩnh. Bạn không phải khai báo nó ở bất cứ đâu.

Từ ví dụ của Andrew:

class Super { 
    public static function get_class1_name()   
    { 
     echo __CLASS__; 
    } 
    public static function get_title() 
    { 
     echo get_called_class(); 
    } 

} 
class Sub extends Super {  
    public static function get_class2_name()   
    { 
     echo __CLASS__; 
    } 

} 
Sub::get_title(); // Echos Sub. 
Sub::get_class1_Name(); // echos super 
Sub::get_class2_Name(); // echos sub 

Vì vậy, bạn không cần phải khai báo bất kỳ biến.

+0

Có sẵn bắt đầu từ PHP 5.3.0 –

+1

Câu trả lời được chấp nhận cũng chỉ là PHP 5.3.0. – Lethargy

+0

Ví dụ này không giải quyết sự khác biệt trong việc truy cập các thuộc tính tĩnh giữa các lớp con và siêu. – beporter

0

May mắn thay, tôi đang làm điều gì đó cho tôi, vì vậy tôi đã nói, vặn nó, tôi đang sử dụng PHP5.3. Nhưng ngay cả như vậy, tôi không thích rằng tôi phải redeclare "có được _class _name" trong mỗi lớp học, có lẽ tôi đang mở rộng như 10 lớp học. Vì vậy, tôi đã đưa ra giải pháp này:

class Super { 
    protected static $classname = __CLASS__; 
    public static function get_classname($name) 
    { 
     static::$classname = $name; 
    } 
    public static function get_classname() 
    { 
     return static::$classname; 
    } 
} 
class Sub1 extends Super { } 
class Sub2 extends Super { } 
class Sub3 extends Super { } 

$classes = get_declared_classes(); 
foreach($classes as $k => $v) 
{ 
    if (is_subclass_of($v, 'Super')) 
    { 
     $v::set_classname($v); 
    } 
} 

echo Sub1::get_classname(); // Sub1 
echo Sub2::get_classname(); // Sub2 
echo Sub3::get_classname(); // Sub3 

Nó có vẻ hơi bẩn, nhưng tôi không nghĩ nó xấu. Với việc này, cuối cùng bạn có thể mở rộng các phương thức tĩnh mà không phải khai báo lại các phương thức.

+2

Như đã đề cập trong câu trả lời của Chacha102, PHP 5.3 cũng có hàm [get_called_class()] (http://uk3.php.net/manual/en/function.get-called-class.php) làm cho việc này không cần thiết. – MrWhite

Các vấn đề liên quan