O Zen e a arte cavalheiresca da programação orientada a objeto (Parte 6)
(Para ver todas as partes desta série clique aqui)
Olá, pessoal, já estamos aqui de volta para falar mais um pouquinho sobre OOP, PHP, e outras siglas igualmente ininteligíveis. Hoje quero falar sobre um tema que sempre gera muita confusão: interfaces. E, é claro, não podemos falar de interface sem olhar a etimologia dessa palavra.
O prefixo inter- vem da preposição latina inter, que significa "entre, no meio de". A palavra face, também de origem latina (fascia), significa "camada externa". Juntando as duas coisas, temos um termo genérico que significa praticamente qualquer coisa em tecnologia. Temos interfaces gráficas, interfaces com o usuário, interfaces RS232, interfaces usb, e por aí vai.
O conceito denominado de interface em OOP é bastante diferente disso tudo. No nosso mundo imaginário de carros, superpoderes, gnomos e outras criaturas fantásticas orientadas a objeto, interfaces são simplesmente definições padronizadas de acesso a funções que estão dentro das classes que as implementam. Falando assim parece bem complicado, mas não é não. Na verdade, na verdade, se a gente olhar com muito cuidado, nós de fato já usamos o conceito de interface aqui mesmo nos artigos anteriores.
Explico: quando nós criamos uma classe, estamos criando também uma interface. Lembra que nós construímos dois carros, um FiatUno e uma FerrariF1, e ambos podiam ->acelerar() ? Justamente! Ajoelhe-se diante do poder das interfaces!
Ao estender a classe Automovel para criar a classe FiatUno e a classe FerrariF1 nós estamos automaticamente implementando a interface usada na classe automóvel nas duas. Assim, temos absoluta certeza que todas as classes-filhas da classe Automovel vão poder ->acelerar(). Esse é exatamente o conceito de interface: a padronização do acesso aos dados e funções de uma classe ou objeto.
Mas o que é realmente interessante é que algum desses gênios malucos que inventaram os conceitos de OOP acordou um belo dia e teve uma idéia brilhante: "Perai, mas eu não preciso ter que criar classes-filhas toda hora pra usar uma interface!". Nasciam as palavras-chave interface e implements, que permitem a criação de interfaces que podem ser usadas entre classes que não tem nenhum parentesco entre si.
E eu estou aqui para provar tudo isso implementando Superpoderes em Automóveis! Você há de concordar que um Automovel não tem nada a ver com um SerHumano, já que eles não têm nenhum parentesco. Como ter certeza que essas classes e todos os seus filhos possam usar objetos da classe SuperPoder de forma padronizada? É fácil:
Primeiro, criamos a interface SuperHeroi:
interface SuperHeroi {public function ativar(SuperPoder $superpoder);
}
Bom, como você pode notar, a função ativar só vai funcionar se você mandar pra ela o SuperPoder desejado durante a chamada da função. Se mandar texto, número ou qualquer outra coisa vai ganhar um erro de presente.
Agora vamos alterar nossas classes Automovel e SerHumano para implementar a interface SuperHeroi:
Class SerHumano implements SuperHeroi { public $nome;
public $vivo;
public function __construct($nome) {$this->nome = $nome;
$this->vivo = true;
}
public function taVivo() { if($this->vivo == true) { print "Sim, eu estou vivo, e meu nome é $this->nome!";
} else { print "...";
}
}
public function ativar(SuperPoder $superpoder){$superpoder->ativar()
}
}
e agora a classe Automovel:
abstract class Automovel implements SuperHeroi {
public $aceleracao;
public $velocidade_atual;
public $cor;
public function acelerar() {
$this->velocidade_atual = $this->velocidade_atual + $this->aceleracao;
print "Acelerando! Agora a velocidade é de " . $this->velocidade_atual . "Km/h!";
} public function ativar(SuperPoder $superpoder){$superpoder->ativar();
}
}
Agora, tanto os objetos SerHumano quanto objetos da classe Automovel (incluindo aqueles das classes FiatUno e FerrariF1, já que pela herança um FiatUno ou uma FerrariF1 sempre têm todas as propriedades e funções da classe Automovel) já podem ->ativar() um SuperPoder. Como a classe SuperPoder é abstrata e ninguém consegue ativar um SuperPoder abstrato, vou ativar a SuperForca:
$meucarro = new FerrariF1('vermelha'); $meucarro->ativar(new SuperForca);
// Meu deus, posso levantar um caminhão!
E os gnomos, você deve estar se perguntando. Eles virão... Eles virão...
