PUBLICIDADE
Este artigo tem nota
9

Autor

everton3x

Everton da Rosa

membro deste janeiro de 2007

Enquete

O mercado de publicidade na web chegou no seu limite?
PUBLICIDADE

quarta-feira, 19 de agosto de 2009

PHP5 Orientado a Objetos: Visibilidade, herança e extensões de classes


Introdução



Com o PHP5 o programador passou a contar com Orientação a Objeto (OO) real, pois no PHP4 e inferiores a OO era apenas "simulada".

Uma das funcionalidades oferecidas pela OO do PHP5 (PHP5-OO) é a extensão de classes, muito útil para acrescentar e modificar funcionalidades de classes sem mexer diretamente no código delas.

Diretamente relacionada com a extensão de classes são os conceitos de visibilidade e de herança, funcionalidades também essenciais para quem quer trabalhar com OO no PHP5.

Este artigo aborda os temas de extensão de classes, herança e visibilidade, procurando expor os seus conceitos e aplicações numa linguagem simples e fácil de entender, voltada principalmente para aqueles usuários que estão ingressando neste campo.

A metodologia utilizada será a de apresentar conceitos e a teoria básica sobre cada assunto, seguida de exemplos de utilização com comentários sobre cada etapa.

Inicialmente estudaremos a questão da visibilidade de propriedades e de métodos, utilizando também exemplos com comentários.

Depois abordaremos a extensão de classes com a adição de métodos e propriedades, explicando o que é e para que serve, seguida de exemplo de utilização.

Como sugestão, aconselha-se a leitura do artigo introdutório (e seus comentários) sobre PHP5-OO, publicado aqui no Código Fonte no link:

[url=http://codigofonte.uol.com.br/artigo/php/php-orientado-a-objetos-para-quem-esta-comecando]PHP Orientado a Objetos Para quem está começando</url>

Uma importante ressalva:

Este artigo é voltado para iniciantes e visa apresentar conceitos e aplicações básicas, não sendo escopo principal a aplicação de qualquer metodologia ou prática de programação específica.

Bom estudo a todos.

Começando a entender visibilidade



A primeira parte de nosso estudo envolverá o conceito de visibilidade de métodos e propriedades.

Mas para fazer isso primeiro precisamos de uma classe. É o que faremos primeiro: uma classe de exemplo com a qual trabalharemos a questão de visibilidade.

<?
/* Script tutorial sobre extensão, herança e visibilidade (PHP Orientado a Objetos).
* @author Everton3x (Everton da Rosa)
* @version 1.0
*/


class MensagemSimples {
public $titulo;
public $texto;

function setTitulo($valor){
$this->titulo = $valor;
}

function setTexto($valor){
$this->texto = $valor;
}

function printTitulo(){
echo $this->titulo;
}

function printTexto(){
echo $this->texto;
}
}


?>


Explicando a classe:



A classe MensagemSimples apenas gera uma mensagem composta por título e texto.

As propriedades $titulo e $texto armazenam o título e o texto da mensagem respectivamente.

Os métodos setTitulo() e setTexto() atribuem valores às propriedades $titulo e $texto.

Os métodos printTitulo() e printTexto() imprimem o título e o texto na tela do navegador.

É uma classe simples, praticamente sem função real, exceto a função didática necessária ao aprendizado.

Vamos agora a uma pequena explanação teórica.

Visibilidade é o nível de acesso que se dá a propriedades e métodos de uma classe. Ela tem três níveis que são determinados pela prefixação das palavras reservadas public, private ou protected antes da definição da propriedade ou do método.

Assim, temos:
  • public define que o acesso à propriedade/método é acessível de qualquer lugar do script;
  • protected define que o acesso somente pode ser feito pela classe que define a propriedade/método e por classes que herdam esses métodos/propriedades (é o que veremos ao estudar extensão de classes);
  • private define o nível mais alto de controle de acesso, onde a propriedade/método somente pode ser acessado pela classe que o define.


No contexto deste artigo, acesso à propriedade ou método significa que ele pode ser utilizado ou ter seu valor modificado ou consultado.

Também, neste artigo, considera-se classe que define o método/propriedade como aquela que possui o código do método/propriedade.

Finda esta explanação teórica, vamos começar a brincar com nossa classe MensagemSimples para aprender sobre a visibilidade public e protected. A visibilidade private será abordada quando estudarmos a extensão e herança.
Notemos que antes das propriedades $titulo e $texto temos a palavra public. Isto significa que são propriedades públicas e podem ser acessadas de qualquer lugar do script.

Vamos a um exemplo:
$msg = new MensagemSimples; // Criamos o objeto instanciando a classe.

// Atribuindo valores às propriedades
$msg->titulo = 'Título da mensagem';
$msg->texto = 'Mensagem de teste.
Testando a visibilidade das propriedades.';

// Recuperando os valores das propriedades.
echo $msg-titulo.'<br>';
echo $msg->texto;


Colocando o código acima no final do nosso script e executando ele no navegador, teremos o seguinte resultado:

Título da mensagem
Mensagem de teste.
Testando a visibilidade das propriedades.

Agora veremos o que acontece se trocarmos a palavra public por private na propriedade $texto.

O resultado exibido pelo navegador será o seguinte:

"Fatal error: Cannot access protected property MensagemSimples::$texto in E:\www\xampplite\htdocs\tutoriais\tutorial.php-oo.visibilidade-heranca-estensao.php on line 33"

O que isso significa?

Significa que não é possível utilizar mais a propriedade $texto fora da classe MensagemSimples.

É justamente por isso que criamos os métodos setTitulo(), setTexto(), printTitulo() e printTexto().

Para utilizarmos nossa classe agora, teremos que substituir o código que não funcionou por este (troque antes o public da propriedade $titulo por protected):
// Atribuindo valores às propriedades
$msg->setTitulo('Título da mensagem');
$msg->setTexto('Mensagem de teste.<br>Testando a visibilidade das propriedades.');

// Recuperando os valores das propriedades.
$msg->printTitulo();
echo '<br>';
$msg->printTexto();
</code>
O resultado no navegador será o seguinte:

Título da mensagem
Mensagem de teste.
Testando a visibilidade das propriedades.

Viu como é fácil! Agora para utilizarmos as propriedades devemos fazer isso somente através da própria classe.

Se para as propriedades é possível selecionar níveis de visibilidade, para os métodos isso é possível?

Sim! É o que veremos agora.

<b>Primeiros passos na visibilidade de métodos</b>

Passaremos agora a estudar a visibilidade dos métodos, porém apenas os níveis public e protected. O nível private ficará para estudarmos junto com o tema extensão de classes e herança.

Tomemos novamente o código da nossa classe:
<code>
class MensagemSimples {
protected $titulo;
protected $texto;

function setTitulo($valor){
$this->titulo = $valor;
}

function setTexto($valor){
$this->texto = $valor;
}

function printTitulo(){
echo $this->titulo;
}

function printTexto(){
echo $this->texto;
}
}

$msg = new MensagemSimples; // Criamos o objeto instanciando a classe.

// Atribuindo valores às propriedades
$msg->setTitulo('Título da mensagem');
$msg->setTexto('Mensagem de teste.<br>Testando a visibilidade das propriedades.');

// Recuperando os valores das propriedades.
$msg->printTitulo();
echo '<br>';
$msg->printTexto();


Vemos que as propriedades estão definidas como protected, porém os métodos não tem definição nenhuma. Isso significa que eles são public, pois quando não se determina nenhum nível de visibilidade, o nível atribuído é o public.

Vamos supor que queiramos que os métodos setTexto() e setTitulo() sejam protected, faríamos a seguinte alteração:
protected function setTitulo($valor){
$this->titulo = $valor;
}

protected function setTexto($valor){
$this->texto = $valor;
}

Se tentarmos executar agora o nosso script, receberíamos a seguinte mensagem:

"Fatal error: Call to protected method MensagemSimples::setTitulo() from context '' in E:\www\xampplite\htdocs\tutoriais\tutorial.php-oo.visibilidade-heranca-estensao.php on line 32"

Isto significa que não mais podemos acessar os métodos setTitulo() e setTexto() a partir de fora da classe.

Mas como vamos acessá-los então?

Para isso devemos fazer uma pequena modificação na nossa classe:
protected function setTitulo($valor){
$this->titulo = $valor;
}

protected function setTexto($valor){
$this->texto = $valor;
}

function printTitulo($valor){
$this->setTitulo($valor);
echo $this->titulo;
}

function printTexto($valor){
$this->setTexto($valor);
echo $this->texto;
}

Note que adicionamos o parâmetro $valor aos métodos printTitulo() e printTexto() e que dentro dos métodos printTitulo() e printTexto() chamamos os métodos setTitulo() e setValor().

O teste do nosso script também deve mudar:
$msg = new MensagemSimples; // Criamos o objeto instanciando a classe.

// Recuperando os valores das propriedades.
$msg->printTitulo('Título da mensagem');
echo '<br>';
$msg->printTexto('Mensagem de teste.<br>Testando a visibilidade das propriedades.');

Isso nos exibirá no navegador, novamente:

Título da mensagem
Mensagem de teste.

Testando a visibilidade das propriedades.

O que fizemos é basicamente chamar os métodos print, passando-lhes os valores desejados e estes métodos chamam os métodos set passando-lhes os valores recebidos e depois imprimem os valores atribuídos pelos métodos set.

Alerto que isto é somente um exemplo didático e que na prática não faríamos desta forma. Isso é apenas para aprendermos a utilizar a visibilidade.

Estendendo classes

Estender uma classe significa criar uma classe (classe-filha) que irá modificar e (ou) ampliar as funcionalidades de outra classes (classe-pai).

Vamos ver isso na prática?

Primeiro vamos repetir o código da classe MensagemSimples (somente para lembrarmos dele), que será a nossa classe-pai.
class MensagemSimples {
protected $titulo;
protected $texto;

protected function setTitulo($valor){
$this->titulo = $valor;
}

protected function setTexto($valor){
$this->texto = $valor;
}

function printTitulo($valor){
$this->setTitulo($valor);
echo $this->titulo;
}

function printTexto($valor){
$this->setTexto($valor);
echo $this->texto;
}
}

Agora, vamos criar a classe-filha:

class MensagemBonita extends MensagemSimples {

}

Vejam que eu inicio com class MensagemBonita, que é o nome da classe-filha, porém não paro aí: eu acrescento a palavra reservada extends seguida do nome da classe-pai, que é MensagemSimples.

Isso significa que a classe MensagemBonita ESTENDE a classe MensagemSimples.

Agora vamos colocar algum código na classe-filha:
class MensagemBonita extends MensagemSimples {
protected $cor;

public function setCor($cor){
$this->cor = $cor;
}

public function imprime($titulo,$texto){
$mensagem = '<h1 style="color: '.$this->cor.'">'.$titulo.'</h1><p>'.$texto.'</p>';
echo $mensagem;
}
}

No código da classe MensagemBonita temos a propriedade $cor, que armazena a cor da fonte do título da mensagem, a qual será atribuída através do método setCor().

O método imprime() recebe o valor a ser utilizado como título e o valor de texto e imprime na tela a mensagem estilizada com a cor.

Vamos testar isso?
$msg = new MensagemBonita;
$msg->setCor('Red');
$msg->imprime('Título da mensagem','Texto da mensagem.');

No navegador deverá aparecer:

Título da mensagem (em vermelho e maior).
Texto da mensagem.

Vemos que a classe inicializada foi a nossa classe-filha, o resto do código você já conhece.

Caso você não tenha percebido, nós estendemos a classe MensagemSimples, porém não fizemos nada com ela ainda. Isso foi proposital, pois na parte seguinte deste artigo, vamos começar a brincar com herança e visibilidade, inclusive com private.

Conhecendo mais a extensão de classes



Agora que sabemos como estender classes, vamos brincar com essa funcionalidade para aprendermos mais sobre extensão, herança e visibilidade.

Sabemos que na nossa classe-pai (MensagemSimples), temos o método pública printTitulo(). O que aconteceria se definíssemos um método com o mesmo nome na classe-filha (MensagemBonita)?

Vejamos:
public function printTitulo($titulo,$texto){
$mensagem = '<h1 style="color: '.$this->cor.'">'.$titulo.'</h1><p>'.$texto.'</p>';
echo $mensagem;
}

Trocando o nome do método imprime() por printTitulo(), deveríamos executá-lo assim:
$msg->printTitulo('Título da mensagem','Texto da mensagem.');

Teríamos o resultado:

Título da mensagem (em vermelho e maior).
Texto da mensagem.

Ou seja, se declararmos um método na classe-filha com o mesmo nome de outro método da classe-pai, o método da classe-filha será sempre chamada em vez do método da classe-pai.

Para utilizarmos o método da classe-pai, devemos utilizar "parent::".

Por exemplo, alterando o método imprime():
public function imprime($titulo,$texto){
parent::printTitulo('Título da classe-pai');
}

Teríamos o seguinte resultado impresso no navegador:

Título da classe-pai

Ou seja, o método imprime() chamou o método printTitulo() da classe-pai.

O mesmo raciocínio é válido para propriedades, ou seja, declarando na classe-filha uma propriedade com mesmo nome da classe-pai, ocorrerá a substituição da propriedade pai pela propriedade filha.

Agora vamos aprender um pouco sobre a visibilidade private.

Para isso vamos alterar o método imprime():
public function imprime($titulo,$texto){
$mensagem = '<h1 style="color: '.$this->cor.'">'.parent::printTitulo($titulo).'</h1><p>'.parent::printTexto($texto).'</p>';
echo $mensagem;
}

Também precisamos trocar os echo por return dos métodos printTitulo() e printTexto() da classe MensagemSimples.

Executando o nosso código, teremos no navegador:

Título da mensagem (em vermelho e maior).
Texto da mensagem.

O que aconteceu aqui foi que o método imprime() chamou (call) os métodos printTitulo() e printTexto() e apresentou o resultado na tela.

Mas o que aconteceria se colocássemos os métodos printTitulo() e printTexto como protected e private (lembre-se que eles são públicos)?

Primeiro como protected:
protected function printTitulo($valor){
$this->setTitulo($valor);
return $this->titulo;
}

protected function printTexto($valor){
$this->setTexto($valor);
return $this->texto;
}

O resultado será:

Título da mensagem (em vermelho e maior).
Texto da mensagem.

Ou seja, tudo ocorreu como o previsto pois a visibilidade dos métodos é protected, ou seja, somente podem ser executados a partir da classe que define o método (MensagemSimples) ou das classes que herdam o método (MensagemBonita).

Mas ao alterarmos de protected para private:
private function printTitulo($valor){
$this->setTitulo($valor);
return $this->titulo;
}

private function printTexto($valor){
$this->setTexto($valor);
return $this->texto;
}

Receberemos no navegador:

Fatal error: Call to private method MensagemSimples::printtitulo() from context 'MensagemBonita' in
F:\xampplite\htdocs\tutoriais\tutorial.php-oo.visibilidade-heranca-estensao.php on line 41


Isto significa que os métodos private somente podem ser executados através da classe que os define (MensagemSimples), ou seja, não são herdados.

O mesmo vale para as propriedades.

Resumindo:

Ao estendermos uma classe, a classe que a estende (classe-filha) herda as propriedades e métodos da classe que estende (classe-pai), ou seja, os métodos e propriedades da classe-pai passam a fazer parte da classe-filha, como se nela fossem definidos.

Exceção para as propriedades e métodos private, que não são herdados, podendo somente serem chamados (call) pela classe que os define, a classe-pai.

Resumo e conclusão



Resumindo o nosso longo artigo:

Os métodos e propriedades podem ter seu acesso restrito através das declarações public, protected e private. Isso chama-se visibilidade.

Quando a visibilidade é public, significa que o método/propriedade pode ser acessado de qualquer parte do script (através da classe que define o método/propriedade, através de classes que herdam eles ou de fora de qualquer classe).

Quando a visibilidade é protected, o método/propriedade somente pode ser acessado pela classe que os define ou pelas que os herdam.

Já, quando a visibilidade é private, o método/propriedade somente pode ser acessado pela classe que os define.

Quanto a extensão, ela é feita com a palavra reservada extends.

Além disso, convém lembrar que ao definirmos na classe filha método ou propriedade com nome igual a método ou propriedade definidos na classe pai, os da classe filha sobrescrevem os da classe pai. Para chamar os métodos/propriedades da classe pai, deve-se usar parent::nomeDoMedodoOu Propriedade.

Espero que este artigo tenha cumprido com seu objetivo que foi o de apresentar os principais conceitos e tópicos sobre visibilidade, herança e extensão de classes, de forma simples, didática e de fácil entendimento, voltado para iniciantes.

Sim   Não   Este artigo foi útil para você?
NotaComentário
8
erickbosco comentou em 15/6/2012

Bom

Bem explanado. Lembra muito a sintaxe da linguagem Java.
10
antenor comentou em 14/3/2012

Excelente

Fico muito grato.Sua didática e capricho saltam aos olhos.O esforço em ser claro nas explicações é importante.Não vou perder um artigo seu.Sou programador de Pascal, utilizo o Delphi, e me identifiquei muito com OO do PHP5.
9
guiski comentou em 25/2/2012

Bom

Muito bom, mas peca em algumas partes, que a explicacao ficou confusa
9
smith comentou em 16/9/2011

Muito bom

Olha, parabéns muito bom.
Acho que precisaria de mais um outro tutorial explicado a questão do parent:: e super classes.
Mais o tutorial está muito bom.
9
brunaluxo comentou em 13/11/2010

Bom

Muito bom o tutorial muito bem explicado .
9
usertop comentou em 10/11/2009

Bom

Exelente tutorial parabens
Regras:
Os comentários seguem as seguintes regras:
  • Todos os comentários são enviados por membros cadastrados no site.
  • A pontuação de comentários de conteúdo do próprio membro não serão computados.
  • Os comentários serão pré-aprovados, porém a equipe do site revisará o conteúdo de todos os comentários podendo ser invalidados (inclusive a pontuação).
  • Os comentários precisam ter, obrigatóriamente, coerência sobre o conteúdo que será comentado.
  • O membro que atingir 5 comentários invalidados não poderá mais comentar dentro do site. Com isso o membro não poderá mais ganhar pontos com comentários.
  • Há um limite de 10 comentários por dia para cada membro.
  • Qualquer comentário após ter sido publicado poderá ser retirado através da opção ( denunciar)

Comente

     (ainda não tem cadastro? clique aqui!)


Máximo de 30 caracteres

Máximo de 255 caracteres
 

© 2006-2013 R&W Informática Ltda. - Todos os direitos reservados. - Política de Privacidade | Mapa do Site