Late Static Binding e o PHP 5.3
Foi lançado a alguns dias a RC2 (release candidate 2) da nova major version do PHP, a versão 5.3. Em alguns dias o PHPSPCast sobre PHP 5.3 deve ir ao ar, mas enquanto ele não chega, vamos entender um pouco mais sobre o problema de Late Static Binding que foi resolvido no PHP 5.3.
O Problema
Eu já tentei explicar conceitualmente, mas, sinceramente? Ninguém entendeu (comigo incluso). Então vamos pra prática. Vamos supor que tenhamos as duas classes abaixo:
class User {
public static function getTipo() {
return 'user';
}
public static function showTipo() {
echo self::getTipo();
}
}
class Admin extends User {
public static function getTipo() {
return 'admin';
}
}
Admin::showTipo(); // imprime: 'user'
A linha 17 do código acima deveria retornar ‘admin’ e não ‘user’ como foi retornado. Esse seria o comportamente esperado. O problema é a palavra reservada self não resolve a chamada estática, assim como a contante __CLASS__ que se for usada, também retorna a classe errada. Ambos não resolvem a chamada em tempo de execução, eles somente verificam ondem foram declaradas e retornam isso.
A solução
A solução não é nenhuma mágica, ou seja, o código não se resolverá sozinho. Quem sabe um dia? A partir da versão 5.3 que será lançada este ano, você poderá usar uma palavra reservada do PHP (que não é nova) e ela – ao contrário do self – irá resolver a chamada em tempo de execução e retornará os valores corretos. A palavra é: static. Sugestivo não?
class User {
public static function getTipo() {
return 'user';
}
public static function showTipo() {
echo static::getTipo();
}
}
class Admin extends User {
public static function getTipo() {
return 'admin';
}
}
Admin::showTipo(); // imprime: 'admin' (PHP 5.3)
Com a troca do self pelo static, o PHP consegue resolver a classe que chamou o método e retornar o valor correto.
O problema (A revolta dos que não foram)
Magicamente, a solução no PHP 5.3 apresenta um (pasme) novo problema. Antes tínhamos o problema (Late Static Binding) de que o PHP não resolvia a classe que chamava o método, o PHP só via em chamadas estáticas o local onde ele foi declarado. Agora nosso problema passa a ser que o PHP não consegue mais ver corretamente chamadas de classes pai, veja o código abaixo e tire suas próprias conclusões.
class User {
public static function getTipo() {
return 'user';
}
public static function showTipo() {
echo static::getTipo();
}
}
class Moderador extends User {
public static function getTipo() {
return 'mod';
}
public static function norris() {
User::showTipo();
parent::showTipo();
self::showTipo();
}
}
class Admin extends Moderador {
public static function getTipo() {
return 'admin';
}
}
Admin::norris();
/**
* Imprime
* user
* admin
* admin
*/
Enfim, o PHP 5.3 está chegando com grandes mudanças, é importante ressaltar que esta é uma major release e que muitas coisas devem ser levadas em consideração. O PHP já possui release candidates para você testar, então se você ainda não testou o que está esperando? Se você puder ainda compilar, não esqueça de rodar um `make test` e enviar os dados para o http://qa.php.net/ para que suas estátisticas dos testes efetuados sejam computados; só isso já é uma contribuição para o projeto. Aguardem essa semana o PHPSPCast sobre as novidades do PHP 5.3, e logicamente, vão se preparando para ele.
A documentação do PHP sobre a implementação de Late Static Binding já existe, inclusive em português e pode ser vista aqui: http://br2.php.net/manual/pt_BR/language.oop5.late-static-bindings.php

