Polimorfismo, Interfaces, Classes Abstractas/Exemplos Simples de Interfaces
From Wiki**3
< Polimorfismo, Interfaces, Classes Abstractas
Encontram-se nas secções seguintes exemplos do conceito de interface. A primeira secção ilustra a maior ou menor capacidade de definição do conceito em duas linguagens:
- Java, onde o conceito é nativo
- C++, onde o conceito é aproximado por outro
A segunda secção (Chihuahua) mostra um exemplo de uma aplicação completa, onde são utilizadas interfaces.
Interfaces em Java e C++
Java
A definição de uma interface, sintacticamente, corresponde a um elenco de métodos, indicando-se, além do nome do método, apenas os tipos dos argumentos e do retorno. É admissÃvel a definição de constantes: identificadores como os dos atributos de qualquer classe. No entanto, estes "atributos" são implicitamente static
e final
.
Considere-se a interface Aluno
que especifica os métodos a fornecer por qualquer aluno.
interface Aluno { void estudar(); }
De modo análogo, considere-se a definição da interface Docente
:
interface Docente { void leccionar(); }
Utilizando as duas interfaces anteriores e definindo alguns métodos adicionais, é possÃvel modelar a interface de um aluno de doutoramento que, por hipótese, dá aulas (por exemplo, como forma de pagar as propinas).
interface Doutorando extends Aluno, Docente { void escreverTese(); void defenderTese(); }
C++
inÃcio de secção opcional
Como em C++ não há o conceito de interface, para definir os conceitos acima é necessário recorrer ao conceito mais próximo: classes virtuais puras (i.e., classes abstractas). O exemplo Java acima, agora aproximado em C++, seria então escrito da seguinte forma.
Classe ("interface") aluno:
class Aluno { public: void estudar() = 0; };
Classe ("interface") docente:
class Docente { public: void leccionar() = 0; };
Classe ("interface") doutorando:
class Doutorando : public Aluno, Docente { public: void escreverTese() = 0; void defenderTese() = 0; };
Note-se que, apesar de se poder aproximar o conceito de interface através de classes abstractas, os dois conceitos diferem substancialmente. Note-se ainda que o paralelo para as classes abstactas de C++ em Java são igualmente classes abstractas (definidas utilizando a palavra chave abstract) e não as interfaces.
fim de secção opcional
Chihuahua
O seguinte exemplo ilustra a utilização de interfaces em Java. Note-se que, além das interfaces, são também utilizadas classes abstractas, por forma a contrastar a utilização de cada conceito. O diagrama UML fornece uma panorâmica do conjunto de interfaces e classes: a amarelo estão representadas as interfaces e a verde as classes abstractas; as classes normais estão a branco.
O exemplo implementa vários conceitos, sendo os principais o de cão e o de vigilante. São definidos outros conceitos que especializam estes e outros que fornecem implementações concretas de cada um. Assim, o conceito de robot é o de um vigilante automático e o de cão de guarda um vigilante canino.
São utilizadas as seguintes interfaces e classes: Cão
, Vigilante
, CãoDeGuarda
, CãoPastor
, Chihuahua
, Robot
, XP
, XP2003
.
Cão
A interface Cão
define as assinaturas dos métodos a que qualquer classe que implemente um cão deve saber responder.
interface Cão { void ladrar(); int nPatas(); }
Embora nada seja expresso na interface, além da assinatura, assume-se que a semântica a associar a cada método é a seguinte:
ladrar
- executa a acção de produzir um latidonPatas
- calcula/retorna o número de patas do cão
As classes que implementem a interface, embora não sejam obrigadas a implementar esta semântica, têm todo o interesse em fazê-lo.
Vigilante
Por seu turno, a interface Vigilante
define as assinaturas dos métodos a que uma entidade "vigilante" deve saber responder.
interface Vigilante { boolean háIntrusos(); void soarAlarme(); }
A semântica a associar pelas implementações é a seguinte:
háIntrusos
- retornatrue
se tiverem sido detectados intrusossoarAlarme
- executa a acção de activar um alarme, e.g. um sinal sonoro
Robot
A interface Robot
é uma especialização de Vigilante
: é um vigilante robotizado que sabe avisar e destruir intrusos.
interface Robot extends Vigilante { void avisarIntrusos(); void destruirIntrusos(); }
As implementações da interface Robot
, além do que já se disse para a interface Vigilante
, devem fornecer a seguinte semântica por método:
avisarIntrusos
- deve ser emitido um aviso (possivelmente, porque depois se segue a invocação do métododestruirIntrusos
- mas não há qualquer garantia...)destruirIntrusos
- a acção a executar corresponde à destruição dos intrusos
Cão de Guarda
A interface CãoDeGuarda
, de modo análogo a Robot
define a assinatura das implementações de um cão de guarda, i.e., um cão vigilante.
interface CãoDeGuarda extends Cão, Vigilante { void morder(); }
Note-se a utilização de herança múltipla.
Cão Pastor
A primeira classe deste exemplo é CãoPastor
. Esta classe implementa parte da interface de um cão de guarda e deixa para as suas subclasses a especificidade associada ao método ladrar
. Embora abstracta, esta classe é uma implementação (ainda que parcial) da interface.
public abstract class CãoPastor implements CãoDeGuarda { public final static int N_PATAS = 4; // métodos privados private void fecharBoca() { /* qualquer coisa */ } private boolean háPredadores() { /* qualquer coisa */ return true; } // interface CãoDeGuarda public void morder() { fecharBoca(); } // inteface Cão public int nPatas() { return N_PATAS; } public abstract void ladrar(); // interface Vigilante public void soarAlarme() { ladrar(); } public boolean háIntrusos() { return háPredadores(); } }
Chihuahua
Um exemplo de uma classe (não abstracta, i.e., implementa ladrar
) derivada de CãoDeGuarda
é a que se segue. Esta classe apenas necessita de implementar o método ladrar
para ficar completa.
public class Chihuahua extends CãoPastor { public void ladrar() { System.out.println("guau, guau"); } }
XP
Supõe-se que a classe XP
existe independentemente das outras descritas até aqui (foi, por exemplo, definida para outro fim). Supõe-se, contudo, que contém funcionalidade útil para uma possÃvel implementação de um robot, i.e., para uma classe que implemente a interface Robot
.
public class XP { public void reboot() { System.out.println("See ya!"); } public void shutdown() { System.out.println("Bye!"); } public void crash() { System.out.println("Nooo! Argh!!!"); } public boolean háIntrusos() { return false; } // detector de vírus }
Note-se a coincidência do nome háIntrusos
: existe na classe XP
e na interface Vigilante
(da qual Robot
herda parte da sua especificação). É necessário garantir que a semântica pretendida é a que o método realmente fornece.
XP2003
Esta é uma implementação de Robot
que reutiliza XP
.
public class XP2003 extends XP implements Robot { // interface Robot public void avisarIntrusos() { System.out.println("Isto é o último aviso!"); } public void destruirIntrusos() { System.out.println("Eu avisei..."); } // interface Vigilante public void soarAlarme() { System.out.println("金曜日ã§ã™ï¼"); } //public boolean háIntrusos() { return true; } // herdado de XP... }
Note-se que o método háIntrusos
é implementado pela superclasse (XP
). A consideração deste aspecto é de importância crucial, pois pode introduzir erros se o comportamento não for o desejado (o que provavelmente acontece: em XP
, os intrusos são vÃrus -- por hipótese -- e em XP2003
, uma implementação de um vigilante robotizado, a semântica é outra).
Aplicação
Considere-se a seguinte classe que exercita os conceitos anteriores:
public class Teste { public static void main(String[] args) { Cão c = new Chihuahua(); Vigilante v = new Chihuahua(); CãoPastor p = new Chihuahua(); Robot r = new XP2003(); XP x = new XP(); XP y = new XP2003(); c.ladrar(); v.soarAlarme(); ((Chihuahua)v).ladrar(); p.soarAlarme(); r.avisarIntrusos(); r.soarAlarme(); x.reboot(); y.crash(); ((XP2003)y).soarAlarme(); } }
Resultado
O resultado da aplicação acima é o seguinte:
$ java Teste guau, guau guau, guau guau, guau guau, guau Isto é o último aviso! 金曜日ã§ã™ï¼ See ya! Nooo! Argh!!! 金曜日ã§ã™ï¼