Late Static Binding e o PHP 5.3

Tuesday, May 19, 2009
By Augusto Pascutti

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

Augusto Pascutti

Augusto Pascutti é desenvolvedor PHP a 5 anos, trabalhou em projetos Open Source como CakePHP, Zend Framework e Habari. É evangelista PHP e de boas práticas, Zend Certified Engineer para PHP 5, fundador/coordenador do PHPSP, host do PHPSPCast e headbanger nas horas vagas.

Website - More Posts

Tags: , ,

  • http://www.ivanrosolen.com Ivan Rosolen

    Hahaha curti a função norris()!

  • http://www.andrerainaud.com.br André Rainaud

    Como nada é perfeito, deram um jeito em um problema e criaram outro ;-)

  • Lucas

    Só tenho uma coisa a dizer, se Norris quer que retorne admin, mesmo que seja para retornar mod, o PHP irá retornar admin, quem é o PHP para desafiar Norris? Vai que um dia ele sisma de embasbacar com o cara e acaba virando um ASP da vida depois de um randnose kick!

    É triste ver como PHP ainda é imaturo quanto a OO.

  • http://www.augustopascutti.com Augusto Pascutti

    Lucas …

    Falar que PHP é imaturo em relação a OO é extremamente errado. Se for assim, ele é tão imaturo em relação a OO quanto Java, por exemplo …..
    São problemas conhecidos, assim como Java possui diversos que devem ser conhecidos pelos programadores. Acontece …..

  • http://reinaldojunior.net Reinaldo

    Falta um echo em cada instrução do método norris()

  • http://www.marceloratton.com Marcelo

    reinaldo:
    o echo ta na função showTipo() …

    public static function showTipo() {
    echo static::getTipo();
    }
    acredito q isso possa ser resolvido passando uma variável como parametro

    public static function showTipo($method) {
    if($method == ‘static’){
    echo static::getTipo();
    } else {
    echo self::getTipo();
    }
    }

    POG??? talvez .. mas como o PHP se comporta com isso ???
    apenas a primeira chamada não se altera .. as outras duas ele busca de acordo com o parametro passado …

  • http://www.phppodcasts.com/2009/08/26/phpspcast-1-php5-3-%e2%80%93-o-bom-o-mal-e-o-namespaces/ PHP Podcasts » PHPSPCast #1: PHP5.3 – O bom, o mal e o Namespaces!