2009-08-14 22 views
17

Długo walczyłem w tej dziedzinie i doszedłem do konkluzji, ale ponieważ wniosek nie był tym, czego szukałem, zanim się poddam, postaram się sprawdzić, inni ludzie mówią. Wiara umiera ostatnia ...Rozszerzanie klas statycznych PHP

Załóżmy, że mamy superklasę (zwaną "Super") i podklasę (zwaną "Sub").

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

Teraz, prawdopodobnie oczekiwać od Sub rozciąga Super, że Sub będzie teraz dziedziczą wszystkich metod Super jest jednak, wydaje się, że tylko odbierać odniesień do metod sub-tych.

Mówię to, bo jeśli zadzwonię:

Sub::get_class_name(); 

wyjście jest "Super", a nie "Sub".

A jeśli zadzwonię:

Sub::get_title(); 

ponownie, wyjście jest "super", a ja nawet tytuł $ zadeklarowanej w Sub.

Oznacza to, że gdy wezwę dziedziczoną funkcję statyczną, zakres funkcji będzie super-klasą, a nie tą, która została wywołana (nawet jeśli wydrukujesz ślad, pokaże on, że połączenie zostało wykonane na nadklasie! !!), i aby uzyskać zakres jako podklasę, na której wywoływane jest wywołanie, muszę ponownie określić tę metodę wewnątrz tej podklasy. Cóż, ten rodzaj porażek ma na celu rozszerzenie klas, prawda?

Moje pytanie brzmi: czy mogę kiedykolwiek rozszerzyć klasę statyczną, zadzwonić do jednej z odziedziczonych metod i mieć zakres podklasy? lub przynajmniej by móc zidentyfikować jego classname? A jeśli nie, dlaczego miałbym kiedykolwiek chcieć rozszerzyć klasy statyczne?

Dzięki!

Odpowiedz

28

Ponownie, nie jest to możliwe przed PHP 5.3.0.

Late Static Binding został wprowadzony w PHP 5.3.0 i pozwala na wykonanie dokładnie tego, co chcesz, za pomocą słowa kluczowego 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() będzie jeszcze powrócić Super choć ma __CLASS__ zawsze zwraca aktualną klasę istota prowadzony metoda jest zadeklarowana (niby jak __FILE__ który zawsze zwraca aktualny plik bez znaczenia, jeśli włączone, czy nie).

W tym przypadku nie masz innego wyjścia, jak tylko ponownie zgłosić funkcję w klasie 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, teraz rozumiem. – treznik

3

Można stosować get_called_class() aby uzyskać nazwę klasy do klasy, do której dzwonisz, nawet jeśli to jest statyczny. Nie musisz tego deklarować w dowolnym miejscu.

Od przykładu Andrzeja:

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 

Dlatego nie trzeba zadeklarować żadnych zmiennych.

+0

Który jest dostępny począwszy od PHP 5.3.0 –

+1

Akceptowaną odpowiedzią jest również tylko PHP 5.3.0. – Lethargy

+0

W tym przykładzie nie uwzględniono różnic w dostępie do właściwości statycznych między klasą podrzędną i super. – beporter

0

Na szczęście robię coś dla mnie, więc powiedziałem, przykręć, używam PHP5.3. Ale mimo to nie podoba mi się, że muszę redeclare "get _class _name" w każdej klasie, może przedłużam jak 10 klas. Więc wymyśliłem to rozwiązanie:

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 

Może wydawać się trochę brudne, ale nie sądzę, że to takie złe. Dzięki temu można w końcu rozszerzyć metody statyczne bez konieczności ponownego deklarowania metod.

+2

Jak wspomniano w odpowiedzi Chacha102, PHP 5.3 posiada również funkcję [get_called_class()] (http://uk3.php.net/manual/en/function.get-called-class.php), która sprawia, że ​​obejście jest zbędne. – MrWhite

Powiązane problemy