Salve
Na parte 1 falamos sobre o café com leite da Orientação a Objetos no PHP: classes, objetos, atributos e métodos. Desta vez vamos nos aprofundar mais no assunto e falar sobre herança, visibilidade e polimorfismo.
Utilizamos a herança para especializar uma determinada classe. No artigo anterior citamos os cães… imaginemos aqueles cães como cães comuns, mas precisamos descrever outro tipo: os cães de guarda, que possuem habilidades que o Max ou o Tirolez não possuem; com OO não precisamos escrever uma classe nova só para o Rush, o pastor alemão do vizinho. Extendemos a classe Cachorro original, herdando suas propriedades e métodos, e alterando o que for conveniente para a nova classe. Por exemplo: podemos dizer que o Rush, ao rosnar induza o cachorro para o qual ele faça de alvo a sentir medo, além de atribuir-lhe um novo método: morder (que originalmente, Max e Tirolez não são capazes de realizar).
Basicamente, para conseguirmos o que descrevi acima, precisamos de extender a classe Cachorro original:
class Cachorro{
//conteudo original
}
class CaoDeGuarda extends Cachorro{
function rosnar($outroCachorro){ /*novo conteúdo deste método*/}
function morder($alvo){ /*conteúdo deste método*/}
}
?>
Para que isso funcione, precisamos conhecer alguns conceitos de OOP: visibilidade e polimorfismo
Visibilidade, que citei na primeira parte, é a declaração de como serão usadas (visíveis) os atributos / métodos de uma classe; os tipos de visibilidade são private, public e protected. Private define que a entidade somente estará acessível em métodos da classe em que a mesma foi declarada. Public define que a entidade pode ser acessada tanto por métodos internos, como por processos externos. Protected é como a private, porém permite que classes filhas acessem a entidade diretamente, sem sobrescrevê-la, e sem permitir o acesso a chamadas externas ao âmbito da classe/objeto.
Geralmente não usamos muito o protected; usamos na maioria das vezes o private para os atributos e o public para os métodos, quando estamos apenas descrevendo dados.Fazemos isso para que sempre seja necessária a execução de um método para alterar o valor de um atributo, podendo assim validar o novo valor, por exemplo. No PHP5, se não definirmos a visibilidade dos métodos, eles assumem como public, assim como se declararmos os atributos com var (PHP4), para manter a compatibilidade.
Polimorfismo: conceito pelo qual entende-se que uma classe filha (extendida), pode conter um mesmo método que a classe ancestral, embora sua execução seja diferente da original, reescrevendo o método da classe pai, utilizando a mesma assinatura; esta por sua vez é a maneira como é declarado o método, sua visibilidade, número e tipo de parâmetros e tipo de retorno; como o PHP não é tipado, ou seja, não atribuímos o tipo das variáveis, podemos nos referenciar a assinatura como visibilidade e número de parâmetros de um dado método.
Para entendermos esses conceitos, ai vai um exemplo:
class A{
private $a1 = ‘1′;
public $a2 = ‘2′;
protected $a3 = ‘3′;
public function mostrar(){
echo ‘Classe A:[';
echo $this->a1;
echo $this->a2;
echo $this->a3;
echo ']<br />’;
}
}
class B extends A{
public function mostrar(){
//aqui estamos utilizando o polimorfismo para reescrever o método mostrar()
echo ‘Classe B:[';
echo $this->a2;
echo $this->a3;
echo $this->a1;
echo ']<br />’;
}
}
$a = new A;
$b = new B;
@$a->mostrar();//mostra Classe A:[123]
@$b->mostrar();//mostra Classe B:[23]
echo $a->a2;//mostra 2
echo $a->a3;//erro
echo $a->a1;//o script nao chega aqui
?>
Esse exemplo nos dá uma idéia do que acontece às propriedades com suas visibilidades definidas.
Voltando aos nossos cães, podemos dizer que a classe CaoDeGuarda é mais específica que Cachorro, sua classe-pai ou superclasse. Podem perguntar ‘Certo, mas o que a tal da visibilidade tem a ver com os cachorros?’; digo que se na parte 1 declarássemos os métodos com as visibilidades específicas, teríamos que mudar muita coisa naquele codigo, e neste, para que tudo ocorresse bem. E mais: do jeito que está agora, podemos alterar o nome do ‘Tirolez’ para ‘123testando’ a qualquer momento.
Vamos alterar as classes para ficarem mais adequadas:
class Cachorro{
private $nome;
private $raca;
private $cor;
private $peso;
private $saude;
public function __construct($n,$r,$c,$p,$s=100){
$this->nome = $n;
$this->raca = $r;
$this->cor = $c;
$this->peso = floatval($p);
$this->saude = intval($s);
}
public function latir(){ /*código que fará o cachorro latir*/ }
public function rosnar($outroCachorro){ /*código que fará o cachorro rosnar para outro */ }
public function mijar($onde){ /*código que fará o cachorro urinar em algum lugar */ }
public function dormir(){ /*código que fará o cachorro dormir e recuperar saúde*/ }
public function setSaude($novaSaude){
$this->saude = (intval($novaSaude) > 100) ? 100 : intval($novaSaude);
}
public function getSaude(){
return $this->saude;
}
}
class CaoDeGuarda extends Cachorro{
function rosnar($outroCachorro){ /*O CaoDeGuarda faz o outroCachorro amedrontar-se*/ }
function morder($alvo){
$saudeOriginal = $alvo->getSaude();
$saudeDepoisDaMordida = $saudeOriginal*0.9;//o alvo perde 10% da saúde a cada mordida
$alvo->getSaude($saudeDepoisDaMordida);
}
}
?>
Bom, podemos fazer a mesma brincadeira da parte 1:
$rush = new CaoDeGuarda(’Rush’,'Pastor’,'Preto/Bege’,50);
$ralf = new Cachorro(’Ralf’,'Fox Paulistinha’,'Preto/Branco’,12);
$ralf->rosnar($rush);//ralf, com seus 30 cm de bravura e estupidez…
$rush->rosnar($ralf);//agora ele viu o tamanho da encrenca;
while($ralf->getSaude() > 50){
$rush->morder($ralf);
}
//sim, gastamos uma boa grana com o veterinário
Assim encerramos esta parte. Na próxima falarei sobre abstração, métodos estáticos, interfaces e mais. Até lá