Programação por Objectos Java

Propaganda
Programação por Objectos
Java
Parte 7: Interfaces
LEEC@IST
Java – 1/31
Interfaces – revisão (1)
• Uma interface é um conjunto de protótipos de
métodos (sem implementações) que especifica um
serviço bem definido:
– As interfaces não podem conter atributos, mas podem
conter constantes.
– A implementação duma interface é realizada pela classe
concreta. Na implementação ou concretização:
• Determina-se os atributos necessários à correcta
implementação da interface.
• Descreve-se o código dos métodos das interface.
LEEC@IST
Java – 2/31
Interfaces – revisão (2)
– Uma interface pode herdar as definições de outra interface.
• Interfaces podem usar polimorfismo.
• Se uma classe concretizar mais de uma interface, e várias
interfaces contiverem métodos com a mesma assinatura, basta
definir uma única implementação.
– Uma interface não pode ser instanciada.
LEEC@IST
Java – 3/31
Interfaces (1)
•
•
•
•
Tanto as classes como as interfaces definem tipos (a unidade
fundamental da programação OO).
Em Java, uma classe só pode estender uma outra classe, mas
pode implementar uma ou mais interfaces.
Para uma dada classe, as classes estendidas e as interfaces
implementadas são denominadas supertipos. A classe em si é
denominada o subtipo.
Uma referência para um objecto do subtipo pode ser usada
sempre que uma referência para um objecto dos seus
supertipos (classes ou interfaces) é necessária.
LEEC@IST
Java – 4/31
Interfaces (2)
• O Java disponibiliza um conjunto de interfaces, de
onde se destaca:
– Comparable: objectos deste tipo têm uma ordem associada
que os permite comparar.
– Iterable: objectos deste tipo disponibilizam um iterador, e
portanto podem ser usadas no ciclo for-each.
• Collection: objectos deste tipo conseguem guardar
outros objectos.
– Set, List, Queue, …
LEEC@IST
Java – 5/31
Interfaces (3)
Sintaxe
Qualif* interface Ident [ extends IdentI [, IdentI ]*] {
[ QualifC* Tipo IdentC = expressão; ] *
[ QualifM* Tipo IdentM ( [TipoP IdentP [, TipoP IdentP ]*); ]*
}
• Qualif: qualificador (visibilidade, entre outros)
• Ident: identificador da interface
• extends IdentI: especialização de interface
LEEC@IST
Java – 6/31
Interfaces (4)
• Qualificadores de interface:
– public: interface publicamente acessível.
– abstract: a interface não pode ser instanciada.
• Por omissão do qualificador public, uma interface é
apenas acessível no pacote onde está definida.
LEEC@IST
Java – 7/31
Interfaces (5)
•
•
•
•
•
Todas as interfaces são implicitamente abstract. Por
convenção, o qualificador abstract é omitido.
Todos os membros são implicitamente public. Por convenção,
o qualificador public é omitido.
Todas as constantes são implicitamente public static final. Por
convenção, os qualificadores são omitidos.
Todos os métodos são implicitamente public abstract. Por
convenção, os qualificadores são omitidos.
Nenhum outro qualificador é permitido às contantes e métodos
duma interface.
LEEC@IST
Java – 8/31
Interfaces (6)
public interface Pilha {
//métodos
boolean vazia();
Object topo();
boolean adicionar(Object o);
void remover();
}
LEEC@IST
Java – 9/31
Herança de interfaces (1)
•
•
•
•
•
Uma interface pode estender mais que uma interface.
As interfaces que são estendidas são denominadas
superinterfaces, enquanto que a nova interface é denominada
subinterface.
Uma subinterface herda todas as constantes declaradas nas
suas superinterfaces.
Se uma subinterface declara uma constante com o mesmo
nome que uma constante herdada (independentemente do
tipo), a constante da subinterface esconde a constante
herdada.
Na subinterface a constante herdada é acedida apenas pelo
seu nome qualificado (superinterface.constante).
LEEC@IST
Java – 10/31
Herança de interfaces (2)
interface X {
int val = 1;
String strx = “X”;
}
interface Y extends X {
int val = 2;
int sum = val + X.val;
String stry = “Y extends” + strx;
}
LEEC@IST
Java – 11/31
Herança de interfaces (3)
•
Se uma interface herda duas ou mais constantes com o mesmo
nome, qualquer referência simples a essa constante é ambígua
e resulta num erro de compilação.
interface A {
String str = “A”;
}
interface B extends A {
String str = “B”;
}
interface D extends B, C {
String d = str;
}
interface C extends A {
String str = “C”;
}
interface D extends B, C {
String d = A.str+B.str+C.str;
}
Erro de compilação: qual str?
LEEC@IST
Java – 12/31
Herança de interfaces (4)
•
•
•
Uma subinterface herda todos os métodos declarados nas suas
superinterfaces.
Se uma subinterface declara um método com a mesma
assinatura, a menos de um retorno covariante, que um ou mais
métodos herdados, o método da subinterface é uma
redefinição dos métodos herdados.
Se uma subinterface herda mais do que um método com a
mesma assinatura, a menos de um retorno covariante, a
subinterface contém apenas um método – o método que retorna
o subtipo comum.
LEEC@IST
Java – 13/31
Herança de interfaces (5)
•
•
Se um método da subinterface difere apenas no tipo de retorno
de um método herdado, ou se dois métodos herdados diferem
apenas no tipo de retorno, e estes retornos não são
covariantes, há um erro de compilação.
Se um método tem o mesmo nome, mas diferentes parâmetros
que um método herdado, o método é uma sobreposição do
método herdado.
LEEC@IST
Java – 14/31
Herança de interfaces (6)
interface X {
void xpto();
Number foo1();
Number foo2();
}
interface Y {
Object foo1();
Object foo2();
}
interface Z extends X, Y {
void xpto(String s);
Integer foo1();
}
• Métodos da interface Z:
–
–
–
–
LEEC@IST
public
public
public
public
void xpto()
void xpto(String)
Integer foo1()
Number foo2()
Java – 15/31
Implementação de interfaces (1)
• Uma classe identifica as interfaces que implementa,
listando-as a seguir à palavra chave implements.
Sintaxe (revisão)
Qualif* class Ident
[ extends IdentC] [ implements IdentI [,IdentI]* ] {
[ Decl_atributos | Métodos ]*
}
LEEC@IST
Java – 16/31
Implementação de interfaces (2)
•
•
As interfaces que uma classe implementa são denominadas as
superinterfaces da classe.
A classe deve disponibilizar uma implementação para todos os
métodos definidos nas suas superinterfaces, senão a classe
tem de ser declarada abstract.
LEEC@IST
Java – 17/31
Implementação de interfaces (3)
•
•
Quando um classe implementa uma interface, a classe pode
aceder às constantes definidas na interface como se tivessem
sido declaradas na classe.
Uma classe que implementa mais do que uma interface, ou que
estende uma classe e implementa uma ou mais interfaces,
sofre dos mesmo problemas de constantes escondidas e
ambiguidade que uma interface que estende mais de uma
interface (ver slides 10, 11 e 12).
LEEC@IST
Java – 18/31
Implementação de interfaces (4)
interface X {
int val = 1;
String strx = “X”;
}
interface Y extends X {
int val = 2;
int sum = val + X.val;
String stry = “Y extends ” + strx;
}
class Z implements Y {
int val = 3;
}
Z z = new Z();
System.out.println(
“z.val=” + z.val +
“ ((Y)z).val=” + ((Y)z).val + /* ou Y.val */
“ ((X)z).val=” + ((X)z).val) /* ou X.val */;
System.out.println(“z.strx=” + z.strx + “ z.stry=” + z.stry;
No terminal é impresso z.val=3 ((Y)z).val=2 ((X)z).val=1
strx=X stry=Y extends X
LEEC@IST
Java – 19/31
Implementação de interfaces (5)
interface A {
String str = “A”;
}
interface B extends A {
String str = “B”;
}
class D implements B, C {
String d = str;
}
interface C extends A {
String str = “C”;
}
class D implements B, C {
String d = A.str+B.str+C.str;
}
Erro de compilação: qual str?
LEEC@IST
Java – 20/31
Implementação de interfaces (6)
•
•
•
Se uma classe implementa várias interfaces com mais do que
um método com a mesma assinatura a classe contém apenas
um tal método.
Se uma classe implementa várias interfaces com mais do que
um método com a mesma assinatura, a menos de um retorno
covariante, a implementação deve definir o método que
retorna o subtipo comum (caso contrário resulta num erro de
compilação).
Se uma classe implementa várias interfaces com mais do que
um método que difere apenas no tipo de retorno, e estes
retornos não são covariantes, há um erro de compilação.
LEEC@IST
Java – 21/31
Implementação de interfaces (7)
interface X {
void xpto();
Number foo1();
Number foo2();
}
interface Z extends X, Y {
void xpto(String s);
Integer foo1();
}
interface Y {
Object foo1();
Object foo2();
}
class ClasseZ implements Z {
public void xpto() {...}
public void xpto(String s) {...}
public Integer foo1() {...}
public Number foo2() {...}
}
É importante identificar os métodos a implementar de uma interface: se
a ClasseZ não disponibilizar a implementação para todos os métodos
definidos nas suas superinterfaces tem de ser declarada abstract (ver
slide 17).
LEEC@IST
Java – 22/31
Implementação de interfaces (8)
•
A implementação da interface Pilha pode ser feita de
diferentes maneiras:
– Baseada numa tabela: PilhaComTabela
– Baseada numa lista ligada: PilhaComLista
•
A interface Pilha corresponde ao tipo de dados abstracto,
enquanto que ambas as classes PilhaComTabela e
PilhaComLista correspondem ao tipo de dados
implementado de duas formas diferentes.
LEEC@IST
public interface Pilha {
//métodos
boolean vazia();
Object topo();
boolean adicionar(Object obj);
void remover();
}
Java – 23/31
Implementação de interfaces (9)
public class PilhaComTabela implements Pilha {
private final int MAX;
private Object pilha[];
private int posLivre; // primeira posição livre
public PilhaComTabela(int max) {
MAX = max;
pilha = new Object[MAX];
posLivre = 0;
}
public boolean vazia() {
return posLivre==0;
}
public Object topo() {
return pilha[posLivre];
}
LEEC@IST
Java – 24/31
Implementação de interfaces (10)
//continuação do slide anterior...
public boolean adicionar(Object obj){
if (posLivre<MAX-1){
pilha[posLivre++] = obj;
return true;
}
else return false;
}
public void remover() {
pilha[posLivre--] = null;
}
public int numMaxElementos() {
return MAX;
}
}
LEEC@IST
Java – 25/31
Implementação de interfaces (11)
public class PilhaComLista implements Pilha {
private ElementoPilha topo;
private int numElementos;
public PilhaComLista(){
topo = null;
numElementos = 0;
}
public boolean vazia() {
return numElementos==0;
}
public Object topo() {
return topo!=null?topo.elemento:null;
}
LEEC@IST
Java – 26/31
Implementação de interfaces (12)
//continuação do slide anterior...
public boolean adicionar(Object obj){
topo = new ElementoPilha(obj,topo);
numElementos++;
return true;
}
public void remover() {
if (topo!=null) {
topo = topo.próximo;
numElementos--;
}
}
public int numElementos() {
return numElementos;
}
}
LEEC@IST
Java – 27/31
Implementação de interfaces (13)
public class ElementoPilha {
Object elemento;
ElementoPilha próximo;
public ElementoPilha(Object elem, ElementoPilha prox){
elemento = elem;
próximo = prox;
}
}
LEEC@IST
Java – 28/31
Implementação de interfaces (14)
•
Definindo as interfaces um tipo, é possível declarar variáveis
com o seu tipo:
Pilha p = new PilhaComTabela(100);
•
Contudo, referências para um tipo de interface, só podem ser
usadas para aceder a membros da própria interface:
p.adicionar(new Integer(100));
p.adicionar(new Character(‘a’));
p.remover();
int max = p.numMaxElementos(); //INVÁLIDO!!!
•
Para contornar este problema pode usar-se um cast:
int max = ((PilhaComTabela)p).numMaxElementos();
LEEC@IST
Java – 29/31
Implementação de interfaces (15)
•
É possível chamar qualquer método de Object com uma
referência para um tipo de interface:
String s = p.toString();
LEEC@IST
Java – 30/31
Implementação de interfaces (16)
•
O programador pode instanciar a pilha que mais lhe interessa:
Pilha p1 = new PilhaComLista();
Pilha p2 = new PilhaComLista();
p1.adicionar(new Integer(5));
p2.adicionar(new Character(‘a’));
•
Se houver interesse em usar PilhaComTabela, em vez de
PilhaComLista, a única alteração reside na instanciação dos
objectos, e não na declaração das referências para o tipo
Pilha:
Pilha p1 = new PilhaComTabela(20);
Pilha p2 = new PilhaComTabela(100);
p1.adicionar(new Integer(5));
p2.adicionar(new Character(‘a’));
LEEC@IST
Java – 31/31
Download