Membros estáticos
Nesta aula, exploramos membros estáticos em PHP: propriedades e métodos static, a diferença entre self e static (late static binding), constantes de classe e o padrão Singleton. Aprendemos a usar esses recursos para compartilhar dados entre instâncias e criar estruturas de código eficientes.
Membros estáticos são elementos de uma classe (propriedades e métodos) que pertencem à própria classe, não a instâncias individuais. Eles são acessados sem a necessidade de criar um objeto, usando o operador de resolução de escopo (::). Nesta aula, veremos como declarar e usar propriedades e métodos estáticos, as diferenças entre self e static (late static binding), constantes de classe e o padrão Singleton, que utiliza membros estáticos para garantir uma única instância.
Propriedades e métodos static
Uma propriedade estática é declarada com a palavra-chave static. Ela é compartilhada por todas as instâncias da classe. Métodos estáticos também são declarados com static e podem ser chamados diretamente na classe, sem instância. Dentro de um método estático, não podemos usar $this (pois não há objeto), mas podemos acessar propriedades estáticas com self:: ou static::.
Exemplo: uma classe que conta quantas instâncias foram criadas.
class Contador {
private static $instancias = 0;
public function __construct() {
self::$instancias++;
}
public static function getInstancias(): int {
return self::$instancias;
}
}
new Contador();
new Contador();
echo Contador::getInstancias(); // 2Propriedades estáticas são úteis para dados que devem ser compartilhados, como configurações globais. Métodos estáticos são frequentemente usados para funções utilitárias que não dependem de estado de instância.
self vs static (late static binding)
Em PHP, self refere-se à classe onde o código está escrito (resolução em tempo de compilação), enquanto static usa late static binding, resolvendo a classe chamadora em tempo de execução. Isso é crucial em herança.
Exemplo:
class Pai {
protected static $nome = 'Pai';
public static function quem() {
echo self::$nome; // sempre 'Pai'
}
public static function quemStatic() {
echo static::$nome; // depende da classe chamadora
}
}
class Filho extends Pai {
protected static $nome = 'Filho';
}
Pai::quem(); // Pai
Filho::quem(); // Pai (self resolve na classe Pai)
Pai::quemStatic(); // Pai
Filho::quemStatic(); // Filho (static resolve na classe Filho)O late static binding permite que métodos estáticos sejam sobrescritos de forma polimórfica. É muito usado em padrões como Factory Method e Active Record.
Constantes de classe
Constantes de classe são valores imutáveis associados à classe. São declaradas com const e, a partir do PHP 7.1, podem ter visibilidade (public, protected, private). São acessadas estaticamente com Classe::CONSTANTE.
Exemplo:
class Config {
public const VERSAO = '1.0';
private const SEGREDO = '123';
public static function getSegredo(): string {
return self::SEGREDO;
}
}
echo Config::VERSAO; // 1.0
echo Config::getSegredo(); // 123Constantes são úteis para valores fixos como configurações, códigos de erro, etc. Diferente de propriedades estáticas, não podem ser alteradas.
Singleton
O padrão Singleton garante que uma classe tenha apenas uma instância e fornece um ponto global de acesso a ela. Geralmente usa-se um método estático para obter a instância única e um construtor privado para evitar criação externa.
Exemplo:
class Singleton {
private static ?Singleton $instancia = null;
private function __construct() {}
public static function getInstancia(): Singleton {
if (self::$instancia === null) {
self::$instancia = new self();
}
return self::$instancia;
}
public function fazerAlgo(): void {
echo "Fazendo algo";
}
}
$obj = Singleton::getInstancia();
$obj->fazerAlgo();Singleton é controverso por introduzir estado global e dificultar testes. Use com moderação e considere injeção de dependência como alternativa.
Boas práticas e observações finais
- Evite abusar de membros estáticos, pois eles criam acoplamento e dificultam testes.
- Use
static::em vez deself::quando esperar que a classe filha possa sobrescrever o comportamento. - Constantes de classe são ideais para valores que nunca mudam, como versões ou limites.
- Singleton pode ser útil para recursos únicos (como conexão de banco), mas prefira contêineres de injeção de dependência.
Referências
- PHP: Membros estáticos - Manual
- PHP: Late Static Bindings - Manual
- PHP: Constantes de classe - Manual
- PHP: Padrões de Design - Singleton
- Refactoring Guru: Singleton em PHP
Exercícios
Crie uma classe
Utilitariocom um método estáticoformatarData($data)que recebe uma string no formato 'Y-m-d' e retorna no formato 'd/m/Y'. Teste chamando o método sem instanciar a classe.✓ Resposta:class Utilitario { public static function formatarData(string $data): string { $dateTime = DateTime::createFromFormat('Y-m-d', $data); return $dateTime ? $dateTime->format('d/m/Y') : 'Data inválida'; } } echo Utilitario::formatarData('2025-04-08'); // 08/04/2025Explique a diferença entre
selfestaticem herança com um exemplo prático que mostre o comportamento de cada um.✓ Resposta:class Animal { protected static $som = 'Som genérico'; public static function emitirSom() { echo self::$som; } public static function emitirSomStatic() { echo static::$som; } } class Cachorro extends Animal { protected static $som = 'Latido'; } Animal::emitirSom(); // Som genérico Cachorro::emitirSom(); // Som genérico (self resolve em Animal) Animal::emitirSomStatic(); // Som genérico Cachorro::emitirSomStatic(); // Latido (static resolve em Cachorro)Crie uma classe
Matematicacom constantes PI = 3.14159 e E = 2.71828. Adicione um método estáticoareaCirculo($raio)que usa PI para calcular a área.✓ Resposta:class Matematica { const PI = 3.14159; const E = 2.71828; public static function areaCirculo(float $raio): float { return self::PI * $raio * $raio; } } echo Matematica::areaCirculo(5); // 78.53975Implemente uma classe
LoggerSingleton que tenha um métodolog($mensagem)para exibir uma mensagem no console (useecho). Garanta que apenas uma instância exista.✓ Resposta:class Logger { private static ?Logger $instancia = null; private function __construct() {} public static function getInstancia(): Logger { if (self::$instancia === null) { self::$instancia = new self(); } return self::$instancia; } public function log(string $mensagem): void { echo "[LOG] $mensagem\n"; } } $logger = Logger::getInstancia(); $logger->log('Aplicação iniciada');Crie uma classe
Configcom uma propriedade estática privada$config(array) e métodos estáticos públicosset($chave, $valor)eget($chave). Useself::para acessar a propriedade.✓ Resposta:class Config { private static array $config = []; public static function set(string $chave, mixed $valor): void { self::$config[$chave] = $valor; } public static function get(string $chave): mixed { return self::$config[$chave] ?? null; } } Config::set('db_host', 'localhost'); echo Config::get('db_host'); // localhost