Pergunta

A partir da versão 5.3, PHP suporta ligação tardia para métodos estáticos. Embora seja um recurso, sem dúvida, útil, só há vários casos em que seu uso é realmente necessário (por exemplo, o Active Record).

Considere estes exemplos:

1. construtores de conveniência (::create())

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

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

Se esta classe pode ser prorrogado (no entanto, não é prorrogado por qualquer classe no mesmo pacote), deve tarde estática ligação ser usado apenas para fazer estendendo-o mais fácil (sem ter que reescrever o método ::create(), e, mais importante, sem ter que se lembrar de fazer isso)?

Nota: esta expressão é usada para trabalho em torno da impossibilidade de chamar métodos em objetos apenas construídos:. new SimpleObject()->doStuff() é inválida no PHP


2. constantes da classe

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

A razão para o uso static:: neste exemplo é semelhante ao anterior. Ele é usado apenas porque esta classe pode ser feito para combinar com as tags de forma diferente formados apenas, estendendo-o e substituindo a constante.


Assim, para embrulhar tudo, são esses usos (e similares) de ligação tardia estática é um exagero? Existe alguma queda de desempenho perceptível? Além disso, faz uso freqüente de ligação tardia reduzir o impulso desempenho global dado por caches opcode?

Foi útil?

Solução

Assim, para embrulhar tudo, são esses usos (e similares) de ligação tardia estática é um exagero? Existe alguma queda de desempenho perceptível? Além disso, faz uso freqüente de ligação tardia reduzir o impulso desempenho global dado por caches opcode?

A introdução de tarde corrige uma falha no modelo de objeto do PHP ligação estática. Não se trata de desempenho, é sobre semântica.

Por exemplo, eu gosto de usar métodos estáticos sempre que a implementação do método não usa $this. Só porque um método é estático, não significa dizer que você não quer substituí-lo às vezes. Antes do PHP 5.3, o comportamento era que nenhum erro foi marcado se você cancelou um método estático, mas PHP seria apenas ir em frente e silenciosamente usar a versão do pai. Por exemplo, o código abaixo impressões 'A' antes do PHP 5.3. Isso é um comportamento altamente inesperado.

estática tardia correções de ligação, e agora o mesmo 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();
?>

Outras dicas

métodos estáticos (precoce ou tardia) criar acoplamento forte e (assim) reduzir a capacidade de teste. você pode criar grandes programas em PHP sem usar mais do que algumas chamadas estáticas. para mim, métodos estáticos final é um não-recurso.

Editar para responder à pergunta de Marco Demaio, como método estático reduzir a capacidade de teste?

Me desculpe se isso é tudo óbvio para você, membros estáticos (ambos os dados e métodos) são útil e não fazer mal se usado de forma responsável, eu estava aludindo ao seu mau uso predominante.

dizer que você tem uma aplicação web que usa um banco de dados SQL. seus objetos de negócios podem recuperar dados usando uma interface estática ou através de polimorfismo. quer

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

ou

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

o último é mais fácil de teste (como em: Eu quero testar que a string sql construído a partir de tais e tais insumos é tal e tal) porque é mais fácil para criar outra implementação da interface dbconn do que é para mudar o significado de db::. por que você gostaria quer? porque você não precisa de um banco de dados real para testar o comportamento de composição sql, e na verdade, é mais fácil de teste para sem um banco de dados real. Além disso, é mais fácil de stub o consumidor sql se seus testes estão preocupados com um outro aspecto da CUT (código sob teste).

testando sempre implica mentir para o código testado sobre seus colaboradores, e abster-se de relações estáticas (o "doublecolon" ou "quadridot") significa a necessidade mentira não ser uma cirurgia enorme, que é um plus, uma vez mais distante o testado código é a partir do código de produção, os menos significativos os resultados do teste são.

Onde eu encontrar uma necessidade de utilizar vinculação estática é permitir que zombando de métodos estáticos para o teste de unidade com PHPUnit. O problema que tenho é que eu não gosto de alterar o código estritamente para permitir zombando, mas eu consigo superar isso.

Para responder à sua pergunta, no entanto, eu apostaria que qualquer custo desempenho este carrega, ele vai pálido em comparação com a maioria dos tempos de execução do programa. Em outras palavras, ele não vai fazer uma diferença notável.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top