Herança e polimorfismo em PHP Orientado a Objetos

Continuando com nossa série sobre PHP Orientado a objetos, hoje vamos falar sobre herança e polimorfismo, ou, a capacidade de criar classes que herdam as propriedades e métodos de classes mãe. Essas classes são conhecidas como subclasses, ou classes derivadas (por derivarem de outras classes). Classes mãe são conhecidas como superclasses.

Ontem você viu Como criar classes em PHP, que são as superclasses. Hoje você vai ver que não é necessário reescrever códigos já escritos anteriormente; se precisar do código de alguma classe já criada, basta criar uma subclasse (classe derivada) e ela terá todas as propriedades e métodos de sua mãe (superclasse).

Além disso, você também vai aprender polimorfismo, que significa ter a capacidade de sobrescrever métodos das superclasses nas subclasses. Isso significa que você poderá ter métodos de mesmo nome na superclasse e subclasse, porém, com ações diferentes.

Vamos deixar de papo e ver como tudo isso funciona na prática, acho mais fácil para você entender.

Herança em PHP Orientado a Objetos

Como descrevi na introdução do artigo, temos superclasses e subclasses na orientação a objetos, sendo que:

  • Superclasses são classes mãe, que não derivam de nenhuma outra classe (saiba mais);
  • Subclasses são classes que são criadas a partir de outras classes (seriam filhas das outras classes) e herdam todas as propriedades e métodos das superclasses.

Veja um exemplo simples:

<?php
// Superclasse (classe mãe)
class Configura {
	// Configura $this->valor na superclasse
	protected $valor = 'Valor qualquer'; 
	
	// Método da superclasse que inverte um valor qualquer
	protected function inverte ( $oque ) {
		// Retorna o valor invertido
		return strrev( $oque );
	}
}

// Subclasse (classe filha)
class Mostra extends Configura {
	// Método da subclasse que apenas retorna um valor
	public function view () {
		// Chama o método que inverte valor da superclasse
		// Com um valor que também foi configurado na superclasse
		return parent::inverte( $this->valor );
	}
}

// Objeto (instância) da subclasse
$mostra = new Mostra;

// Exibe o que o método da subclasse tem para mostrar
// Neste caso: reuqlauq rolaV (valor invertido)
echo $mostra->view();

Talvez o exemplo acima seja um pouco grande para que você entenda logo de cara, mas vai por mim, não é nada complicado.

Vamos por partes.

A superclasse (ou classe mãe)

class Configura {
	protected $valor = 'Valor qualquer'; 
	
	protected function inverte ( $oque ) {
		return strrev( $oque );
	}
}

Veja que tenho uma propriedade:

protected $valor = 'Valor qualquer';

E um método:

protected function inverte ( $oque ) {
	return strrev( $oque );
}

Perceba também, que ambos são "protected", ou seja, não podem ser acessados diretamente pelo programa, somente pela superclasse e suas subclasses.

No método, estou apenas chamando uma função que inverte os valores de uma string qualquer, strrev.

A subclasse (ou classe filha)

class Mostra extends Configura {
	public function view () {
		return parent::inverte( $this->valor );
	}
}

Essa classe não tem nenhuma propriedade, porém, tem um método públic (public) chamado view. Este método não faz nada além de retornar um valor.

O que pode ser confuso aqui, é que a subclasse não tem nenhuma propriedade chamada "valor", ou método chamado "inverte", e mesmo assim, consigo utilizar ambos indiretamente quando crio o objeto e chamo o método view:

$mostra = new Mostra;
echo $mostra->view();

Isso acontece porque a subclasse herdou tudo o que a superclasse tinha, tanto propriedades quanto métodos.

Para acessar propriedades da superclasse na subclasse, simplesmente utilize a palavra $this.

<?php
// Superclasse
class Configura {
	protected $valor = 'Valor qualquer'; 
}

// Subclasse
class Mostra extends Configura {
	function __construct() {
		// Exibe o valor da superclasse
		echo $this->valor;
	}
}

// Objeto da subclasse
$mostra = new Mostra;

Veja que $this->valor está exibindo o valor da superclasse, mesmo estando dentro da subclasse.

Porém, se você criar outra propriedade de mesmo nome na subclasse, a propriedade da superclasse será sobrescrita, e o valor da subclasse passará a valer.

<?php
// Superclasse
class Configura {
	protected $valor = 'Valor qualquer'; 
}

// Subclasse
class Mostra extends Configura {
        // Agora $valor tem outro valor
	protected $valor = 'Outro valor';
	
	function __construct() {
		// Exibe o valor da superclasse
		echo $this->valor;
	}
}

// Objeto da subclasse
$mostra = new Mostra;

Além disso, também posso utilizar as palavras parent (para me referir à superclasse) e self (para fazer referência à classe atual, ou classe filha).

Veja:

<?php
// Superclasse
class Configura {
	protected $valor = 'Valor qualquer'; 
	
	// Método ver() na superclasse
	protected function ver () {
		return 'Classe mãe: ' . $this->valor . '<br>'; 
	}
}

// Subclasse
class Mostra extends Configura {
	public $valor = 'Outro valor';
	
	function __construct() {
		// Exibe o valor da superclasse
		echo self::ver(); // Subclasse
		echo parent::ver(); // Superclasse
		echo $this->ver(); // Subclasse
	}
	
	// Método ver() na subclasse
	protected function ver () {
		return 'Classe filha: ' . $this->valor . '<br>'; 
	}
}

// Objeto da subclasse
$mostra = new Mostra;

Isso vai retornar exatamente:

Classe filha: Outro valor
Classe mãe: Outro valor
Classe filha: Outro valor

Deu pra entender?

Polimorfismo em PHP Orientado a Objetos

Polimorfismo simplesmente significa reescrever um método da superclasse na subclasse, veja:

<?php
// Superclasse
class Configura {
	public function ver () {
		echo 'Sou a superclasse! <br>';
	}
	
	function __construct() {
		$this->ver();
	}
}

// Subclasse
class Mostra extends Configura {
	public function ver () {
		echo 'Sou a subclasse! <br>';
	}
	
	function __construct() {
		$this->ver();
	}
}

// Objeto da superclasse
$superclasse = new Configura;

// Objeto da subclasse
$subclasse = new Mostra;

O método "ver()", foi reescrito na subclasse, por isso, terá um resultado diferente da sua classe mãe, a superclasse.

Se eu apagar o método da subclasse, teremos duas vezes a mensagem: "Sou a superclasse!" na tela.

<?php
// Superclasse
class Configura {
	public function ver () {
		echo 'Sou a superclasse! <br>';
	}
	
	function __construct() {
		$this->ver();
	}
}

// Subclasse
class Mostra extends Configura {
	function __construct() {
		$this->ver();
	}
}

// Objeto da superclasse
$superclasse = new Configura;

// Objeto da subclasse
$subclasse = new Mostra;

Bem simples essa parte.

Concluindo

Ainda não tem muito para conversarmos sobre programação orientada a objetos, porém, com a aula de ontem:

E essa que você acabou de ler, creio que já vai dar para você brincar bastante com POO em PHP (ou no inglês, OOP).

Não deixe de visualizar todas as aulas do nosso curso gratuito de PHP.