Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá pessoal, eu tava lendo sobre polimorfismo e no artigo tem o seguinte exemplo: Uma classe Empregado tem uma método "clockin". Aí tem outras duas classes que herdam essa classe Empregados. Essas classes são Balconista e Programador. Aí ele fala que a classe Balconista pode registrar a data e a hora em um catão, enquanto a classe Programador pode assinar na rede corporativa! Entao como seria mais ou menos esse metodo "clockin"? Ele só salvaria a data e a hora, enquanto as classes que herdam esse metodo é que iriam formatar e tratar de formas diferentes cada tipo de empregado? Ou seja, metodo "clockin" seria generico? Servindo pra qualquer classe filha?
Obrigado!
Gabriel Heming, falando em "funções genéricas" no contexto do falcao544 seria o get/set que você colocou na abstrata
A explicação está muito boa.
>
Como Empregado é uma pessoa, o mais interessante é ser uma classe abstrata.
Porque? Eu não poderia usar uma interface?
Obrigado!
Porque? Eu não poderia usar uma interface?
Não há porque não utilizar uma interface. Antigamente, todas as classes deveriam possuir interfaces. Essa, entretanto, é a pergunta errada.
É melhor eu explicar porque eu utilizei uma classe abstrata.
Definição do manual do php sobre Interface:
Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.
It's possible for interfaces to have constants. Interface constants works exactly like class constants except they cannot be overridden by a class/interface that inherits them.
Veja bem, uma interface permite definir métodos que uma classe deve implementar. Entretanto, uma interface não faz nada além disso. Basicamente como um 'contrato'. Em monólogo, seria mais ou menos isso:
- Eu deixo você 'me implementar'. Entretanto, você deve implementar esses métodos. Senão eu 'lançarei' um erro fatal!
A interface define o que uma classe deve implementar de métodos Públicos ou Constantes. Você não pode criar métodos private ou protected em uma interface, somente public. Todos os métodos de uma interface são abstratos.
Já uma classe abstrata, é um tipo de classe especial que não pode ser instanciada, somente suas classes Filhas.
Assim como na interface, você define métodos que somente serão implementados nas classes filhas. Com apenas uma diferença da Interface, esses métodos(abstratos) podem ser também do tipo protected (não podem ser private... não existe herança em métodos private).
Entretanto, uma classe abstrata, continua sendo uma classe. E como de praxe, você pode criar métodos, constantes e variáveis e tudo que uma classe permite. Menos instanciá-la.
Como é uma classe especial, no nosso exemplo, foi possível implementar o método getNome. Utilizando uma interface, não poderíamos ter criado esse método na interface. Teria de ser criado nas classes filhas, e cairíamos no conceito DRY (Don't Repeat Yourself).
Se você necessita de métodos com a mesma funcionalidade para ambas as classes filhas, crie uma classe abstrata. Se não houver a ocorrência de métodos com a mesma funcionalidade, crie uma Interface.
Mais informações, você pode ver neste link: Interfaces X Classes Abstratas
A diversas outras diferenças e semelhanças entre classe abstrata e interface. Mas não me prolongarei, pois o artigo abaixo é bem completo nesse quesito.
Retirado do artigo acima:
Vale lembrar que, se todos os método da Classe abstrata forem sem corpo, ela se torna uma Interface.
Como é uma classe especial, no nosso exemplo, foi possível implementar o método getNome. Utilizando uma interface, não poderíamos ter criado esse método na interface. Teria de ser criado nas classes filhas, e cairíamos no conceito DRY (Don't Repeat Yourself).
Nesse caso você não quis se referir ao método clockin? Pois o getNome teria o mesmo comportamento não? Ao contrário do clockin?
Obrigado mais uma vez! Ótima explicação!
Não. Realmente me refiro ao método getNome.
Veja bem, uma interface, ou métodos abstratos de uma classe, tem como predefinição realizar um contrato para que as classes filhas implementem, de forma diferentes, os mesmos métodos. Quando você está em dúvida em utilizar uma interface ou classe abstrata, pense se você possuirá um método que, em todas as classes filhas, realizará a mesma tarefa. Caso possuir, deverá utilizar uma classe abstrata. Como no exemplo anterior, eu utilizei uma classe abstrata porque queria utilizar o método setNome e getNome. Vamos a outro exemplo.
Imagine que ao invés de criar uma classe abstrata, você crie uma inteface.
Interface Empregado:
Interface Class Empregado {
public function clockin();
public function getNome();
public function setNome( $nome );
}
Classe Balconista:
Class Balconista extends Empregado {
public function clockin() {
$data = new DateTime();
printf( "%s registrou o cartão as %s de %s \n", $this->getNome(), $data->format( 'H:i:s' ), $data->format( 'd/m/y' ) );
public function getNome() {
return $this->nome;
}
public function setNome( $nome ) {
$this->nome = $nome;
}
}
}
Definimos os métodos necessários na interface. Veja bem que foi removida a variável nome. Uma interface suporta somente métodos públicos e constantes.
Classe Programador:
Class Programador extends Empregado {
public function clockin() {
$data = new DateTime();
printf( "%s assinou na rede corporativa \n", $this->getNome() );
public function getNome() {
return $this->nome;
}
public function setNome( $nome ) {
$this->nome = $nome;
}
}
}
Criamos nossos 3 métodos (clockin, getNome, setNome). Todas as classes filhas terão de implementar esses métodos. As classes terão o mesmo funcionamento que possuíam antigamente. Realizar o clockin e incluir seu nome.
Agora, a diferença é que, teremos que criar os métodos getNome e setNome nas classes Balconista e Programados. Ambas as classes possuirão a MESMA tarefa e realizarão da MESMA forma. Logo, serão as mesmas linhas de códigos em ambas ( CTRL+C e CTRL+V ) e estaremos duplicando código sem necessidade.
Caso algum dia, o getNome, passe a retornar, além do nome, o sobrenome. Teremos de modificar em ambas as classes, o que não seria nada interessante, além de uma grande dor de cabeça.
Esse foi o motivo de eu ter usado uma classe abstrata.
Hum... Estou começando a entender melhor! Muito obrigado pela paciência! Em relação ao exemplo citado acima, o correto não seria "implements" no lugar de "extends"? E quando eu uso "extends" ou "implements" eu posso me referir aos métodos/variáveis da classe pai e aos métodos da interface, usando o $this? Outra dúvida, porque eu não posso usar $this com variáveis estáticas?
Muito Obrigado mais uma vez!
"extends" sempre quando for herença.
"implements" sempre q a sua classe usar um interface.
> E quando eu uso "extends" ou "implements" eu posso me referir aos métodos/variáveis da classe pai e aos métodos da interface, usando o $this?
Só se forem **public** ou **protected**;
> Outra dúvida, porque eu não posso usar $this com variáveis estáticas?
Porque $this está no contexto do objeto, enquanto propriedades estáticas estão no contexto da classe.
Ao invés de usar $this->variable, você usa self::$variable.
Seguindo o que você especificou, cada classe filha possui um definição específica, não se repetindo em nenhuma classe.
Logo, não há a necessidade de criar uma função genérica. Apenas especifique que as classes filhas deverão implementá-la e, então, implemente-a nas filhas.
Isso pode ser feito através de uma interface ou uma classe abstrata.
Como Empregado é uma pessoa, o mais interessante é ser uma classe abstrata. Assim, pode-se implementar o método set/get do nome da pessoa na classe Pai. Com uma interface, não seria possível.
Class Empregado:
Abstract Class Empregado {
Class Balconista:
Class Balconista extends Empregado {
Class Programador:
Class Programador extends Empregado {
Como não há nada que se beneficie do polimorfismo, criei a classe RelogioPonto.
Class RelogioPonto:
Class RelogioPonto {
Implementação:
Saída:
>
Gabriel Heming assinou na rede corporativa
Fulano da Silva registrou o cartão as 11:12:36 de 23/05/12
Com poucas linhas de código e nenhuma mudança na hora de registrar a entrada de um Programador ou Balconista. A classe RelogioPonto realizou a MESMA 'tarefa' de FORMAS diferente
Apesar de ser um exemplo básico, você pode expandir a implementação de clockin e não apenas imprimir o que será feito.
No link abaixo, o João Batista Neto explica vários tópicos referentes a OO. Polimorfismo é um deles.
PHP Orientado a Objetos