2009-08-14 22 views
17

He estado luchando en esta área desde hace días, y he llegado a una conclusión, pero como la conclusión no era lo que estaba buscando, antes de darme por vencido, intentaré ver qué otras personas dicen La fe muere la última ...Extendiendo clases estáticas PHP

Digamos que tenemos una superclase (llamada "Super") y una subclase (llamada "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'; 
} 

Ahora, es probable que esperar ya que se extiende Sub Súper, que ahora sería Sub heredar todos los métodos de Súper, sin embargo, parece ser sólo para recibir referencias a los métodos de la Sub.

Digo esto porque si llamo:

Sub::get_class_name(); 

la salida es "Super", y no "Sub".

Y si llamo:

Sub::get_title(); 

de nuevo, la salida es "super", e incluso tengo el título $ declarada en Sub.

Esto significa que cuando invoco una función estática heredada, el alcance de la función será la superclase, no la que se invoca (incluso si imprime la traza inversa, ¡mostrará que la llamada se realizó en la superclase! !!), y para obtener el alcance como la subclase sobre la que se realiza la llamada, necesito redeclarar ese método dentro de esa subclase. Bueno, este tipo de derrotas el propósito de extender las clases, ¿no?

Así que mi pregunta es, ¿puedo alguna vez extender una clase estática, llamar a uno de los métodos heredados y tener el alcance de la subclase? o al menos para poder identificar su nombre de clase? Y si no, ¿por qué querría extender las clases estáticas?

Gracias!

Respuesta

28

Nuevamente, esto no es posible antes de PHP 5.3.0.

Late Static Binding se introdujo en PHP 5.3.0 y le permite hacer exactamente lo que quiere a través de la palabra clave 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() seguirá volver Super aunque tiene __CLASS__ siempre devuelve la clase actual del método que se está ejecutando se declara en (algo así como __FILE__ que siempre devuelve el archivo actual no importa si se incluye o no).

Para eso no tiene más remedio que volver a declarar la función en la clase 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

Bien, ahora lo entiendo. – treznik

3

Usted puede utilizó get_called_class() para obtener el nombre de clase de la clase a la que llama, incluso si es estática. No tienes que declararlo en ningún lado.

del ejemplo de 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 

Por lo tanto usted no tiene que declarar las variables.

+0

Cuál está disponible comenzando PHP 5.3.0 –

+1

La respuesta aceptada es también PHP 5.3.0 solamente. – Lethargy

+0

Este ejemplo no aborda las diferencias en el acceso a las propiedades estáticas entre las subclases y superclases. – beporter

0

Afortunadamente, estoy haciendo algo por mí, así que dije, lo jodo, estoy usando PHP5.3. Pero aún así, no me gusta que tenga que redeclarar "get _clase _name" en todas las clases, tal vez me extiendan como 10 clases. Así me ocurrió con esta solución:

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 

Podría parecer un poco sucio, pero no creo que sea tan malo. Una vez hecho esto, finalmente puede extender los métodos estáticos sin tener que volver a declarar los métodos.

+2

Como se mencionó en la respuesta de Chacha102, PHP 5.3 también tiene la función [get_called_class()] (http://uk3.php.net/manual/en/function.get-called-class.php) que hace que esta solución sea superflua. – MrWhite