2009-11-29 14 views
13

Comenzando con la versión 5.3, PHP admite late binding para métodos estáticos. Si bien es una característica indudablemente útil, solo hay varios casos en los que su uso es realmente necesario (por ejemplo, el patrón de registro activo).¿Es posible usar en exceso el enlace estático tardío en PHP?

Considere estos ejemplos:

1. constructores de conveniencia (::create())

class SimpleObject 
{ 
    public function __construct() { /* ... */ } 

    public static function create() 
    { 
     return new static; // or: return new self; 
    } 
} 

Si esta clase se puede extender (sin embargo, no es extendido por cualquier clase en el mismo paquete), debe el enlace estático tardío se usa solo para facilitar la extensión (sin tener que volver a escribir el método ::create(), y, lo que es más importante, sin tener que acordarse de hacerlo).

Nota: esta expresión idiomática se utiliza para evitar la imposibilidad de llamar a métodos en objetos simplemente construidos: new SimpleObject()->doStuff() no es válido en PHP.


2. Clase constantes de

class TagMatcher 
{ 
    const TAG_PATTERN = '/\<([a-z\-]+?)\>/i'; 

    private $subject; 

    public function construct($subject) { $this->subject = $subject; } 

    public function getAllTags() 
    { 
     $pattern = static::TAG_PATTERN; 
     preg_match_all($pattern, $this->subject); 
     return $pattern[1]; 
    } 
} 

La razón para utilizar static:: en este ejemplo es similar a la anterior. Se usa solo porque se puede hacer que esta clase coincida con etiquetas formadas de forma diferente simplemente extendiéndola y anulando la constante.


lo tanto, para envolverlo todo, son estos usos (y otras similares) en los últimos tiempos estática de unión se una exageración? ¿Hay algún golpe de rendimiento notable? Además, ¿el uso frecuente de enlace tardío reduce el aumento del rendimiento general otorgado por los cachés de código de operación?

+0

Bueno, el segundo se puede lograr anulando una variable privada y usando '$ this', también, ¿no? ¿O estoy malentendiendo algo? – Franz

+1

Sí, pero simplemente no podría llegar a un mejor ejemplo ... Tenerlo como 'const' significa evitar copiarlo a través de todas las instancias. E incluso si PHP's copy-on-write optimizara esto, ciertamente se ve mejor como una constante de clase, porque en realidad es un valor constante para toda la clase. –

+0

... y por todo eso, quise decir que en este caso el uso de variables de instancia parece una solución, mientras que 'static ::' no. –

Respuesta

13

Así que, para envolverlo todo, ¿estos usos (y otros similares) de la vinculación estática tardía son una exageración? ¿Hay algún golpe de rendimiento notable? Además, ¿el uso frecuente de enlace tardío reduce el aumento del rendimiento general otorgado por los cachés de código de operación?

La introducción del enlace estático tardío corrige un defecto en el modelo de objetos de PHP. No se trata de rendimiento, se trata de semántica.

Por ejemplo, me gusta usar métodos estáticos cada vez que la implementación del método no utiliza $this. El hecho de que un método sea estático no significa que a veces no quieras anularlo. Antes de PHP 5.3, el comportamiento era que no se marcaba ningún error si se reemplazaba un método estático, pero PHP simplemente seguiría adelante y usaría silenciosamente la versión de los padres. Por ejemplo, el siguiente código imprime 'A' antes de PHP 5.3. Es un comportamiento altamente inesperado.

Fijación estática tardía lo corrige, y ahora el mismo código imprime 'B'.

<?php 
class A { 
    public static function who() { 
    echo __CLASS__; 
    } 
    public static function test() { 
    static::who(); 
    } 
} 

class B extends A { 
    public static function who() { 
    echo __CLASS__; 
    } 
} 

B::test(); 
?> 
+0

Por favor, comentar después de downvote. – erenon

+11

Sé que este es un hilo viejo, pero lo encontré a través de google. Su código de ejemplo debería imprimir 'A' independientemente de la versión de PHP. Para activar enlaces estáticos tardíos, use la palabra clave estática. P.EJ.reemplazar self :: who(); con static :: who(); y debería imprimir 'B' – Maurice

3

métodos estáticos (enlace temprano o tardío) crean un acoplamiento ajustado y (por lo tanto) reducen la capacidad de prueba. puede crear programas grandes en PHP sin utilizar más de unas pocas llamadas estáticas. para mí, los métodos estáticos tardíos no son características.

editar para responder la pregunta de Marco Demaio, ¿cómo el método estático reduce la capacidad de prueba?

Lo siento si esto es todo obvio para usted, los miembros estáticos (tanto los datos y métodos) son útiles y no hacer daño si se utiliza de manera responsable, yo estaba en alusión a su mal uso frecuente.

dicen que tiene una aplicación web que usa una base de datos SQL. sus objetos comerciales pueden recuperar datos usando una interfaz estática o mediante polimorfismo. ya sea

class MyBusinessObject 
extends... 
{ 
    public function doThisOrThat(...) 
    { 
    $results = db::query('sql string...'); 
    ... 
    } 
} 

o

class MyBusinessObject 
extends... 
{ 
    public function __construct(dbconn $db) 
    { 
    $this->db = $db; 
    } 
    private $db; 
    public function doThisOrThat(...) 
    { 
    $results = $this->db->query('sql string...'); 
    ... 
    } 
} 

el último es más fácil para poner a prueba (como en: Quiero probar que la cadena sql construido a partir de tales y tales entradas es tal y tal) porque es más fácil crear otra implementación de la interfaz dbconn que cambiar el significado de db::. por qué querrías?porque no necesita una base de datos real para probar el comportamiento de composición de sql, y de hecho es más fácil probar sin una base de datos real. Además, es más fácil desconectar al consumidor de sql si sus pruebas están relacionadas con otro aspecto de la CUT (Código bajo prueba).

probar siempre implica mentir al código probado sobre sus colaboradores, y abstenerse de interfaces estáticas (el "doblecolon" o "quadridot") significa que no tiene que ser una cirugía masiva, lo cual es una ventaja, ya que cuanto más el código probado proviene del código de producción, menos significativos son los resultados de la prueba.

+0

+1 Desde que comencé a usar instancias sobre métodos estáticos, las cosas se volvieron mucho más fáciles en todo –

+0

@just someone: ¿a qué te refieres cuando dices que los métodos estáticos crean un acoplamiento ajustado que reduce la capacidad de prueba? No entiendo cómo pueden reducir la capacidad de prueba. –

+0

@Marco Demaio: vea la respuesta editada. –

1

Dónde encuentro la necesidad de utilizar finales de enlace estático es permitir burla de los métodos estáticos para las pruebas unitarias con PHPUnit. El problema que tengo es que no me gusta cambiar el código estrictamente para permitir burlas, pero puedo superarlo.

Para responder a su pregunta, sin embargo, apostaría que sea cual sea el costo de rendimiento que esto conlleva, palidecerá en comparación con la mayoría de los tiempos de ejecución del programa. En otras palabras, no hará una diferencia notable.

Cuestiones relacionadas