Você está na página 1de 33

Java 2 Standard Edition

Interfaces e polimorfismo
Helder da Rocha (helder@acm.org)

argonavis.com.br 1

O que polimorfismo
Polimorfismo (poli=muitos, morfo=forma) uma caracterstica essencial de linguagens orientadas a objeto Como funciona?
Um objeto que faz papel de interface serve de intermedirio fixo entre o programa-cliente e os objetos que iro executar as mensagens recebidas O programa-cliente no precisa saber da existncia dos outros objetos Objetos podem ser substitudos sem que os programas que usam a interface sejam afetados
2

Objetos substituveis
Polimorfismo significa que um objeto pode ser usado no lugar de outro objeto
Usurio do objeto enxerga somente esta interface freia() acelera() vira(1) Uma interface Mltiplas implementaes

Onibus Veiculo
freia() acelera() vira(direcao)

Jipe Jegue Aviao

Subclasses de Veiculo! (herdam todos os mtodos)

Por exemplo: objeto do tipo Manobrista sabe usar comandos bsicos para controlar Veiculo (no interessa a ele saber como cada Veiculo diferente vai acelerar, frear ou mudar de direo). Se outro objeto tiver a mesma interface, Manobrista saber us-lo

Usurio de Veiculo ignora existncia desses objetos substituveis

Programas extensveis
Novos objetos podem ser usados em programas que no previam a sua existncia
Garantia que mtodos da interface existem nas classes novas Objetos de novas classes podem ser criados e usados (programa pode ser estendido durante a execuo)
... freia() acelera() vira(0) Veiculo
freia() acelera() vira(direcao)

Jipe

LandRover AirBus Concorde LandRover

Mesmo nome. Implementaes diferentes.

Veiculo v1 = new Veiculo(); Veiculo v2 = new Aviao(); Veiculo v3 = new Airbus(); v1.acelera(); // acelera Veiculo v2.acelera(); // acelera Aviao v3.acelera(); // acelera AirBus

Aviao

Concorde

AirBus

Interface vs. implementao


Polimorfismo permite separar a interface da implementao A classe base define a interface comum
No precisa dizer como isto vai ser feito
No diz: eu sei como frear um Carro ou um nibus
Estabelece uma interface comum
Veiculo freia() {} acelera() {} vira(dir) {}

Diz apenas que os mtodos existem, que eles retornam determinados tipos de dados e que requerem certos parmetros
Diz: Veiculo pode acelerar, frear e virar para uma direo, mas a direo deve ser fornecida

Onibus freia() {} acelera() {} vira(dir) {}

Carro freia() {} acelera() {} vira(dir) {}

Implementaes da interface (dizem como fazer)

Como funciona
Suporte a polimorfismo depende do suporte ligao tardia (late binding) de chamadas de funo
A referncia (interface) conhecida em tempo de compilao mas o objeto a que ela aponta (implementao) no O objeto pode ser da mesma classe ou de uma subclasse da referncia (garante que a TODA a interface est implementada no objeto) Uma nica referncia, pode ser ligada, durante a execuo, a vrios objetos diferentes (a referncia polimorfa: pode assumir muitas formas)

Ligao de chamadas de funo


Em tempo de compilao (early binding) - C!
chamada 1 . . . chamada 2 funo()
0xff52

funo()

0xff52 endereo fixo!

0xff52

Cdigo da funo . . .

no pode haver polimorfismo pois cdigo est sempre ligado chamada da funo

Em tempo de execuo (late binding) - Java!


chamada 1 . . . chamada 2 v.freia()
??? ligao entre referncia e objeto durante a execuo

v.freia()

??? mecanismo que faz a ligao

0xff52

Carro freia()

0cff99

Onibus freia()

existe polimorfismo pois cada chamada poder causar execuo de cdigo diferente

dependem do objeto ao qual a referncia atual aponta

Exemplo (1)
Considere a hierarquia de classes ao lado
Manobrista manda mensagens para Veiculo Veiculo freia() {...} acelera() {...} vira(direcao) {...}
Manobrista estaciona (Veiculo v) {...}

usa

herdam interface Herdam interface mas sobrepem implementao (cada objeto executa o mtodo de forma particular)

Jegue freia() {...} acelera() {...} vira(direcao) {...}

LandRover freia() {...} acelera() {...} vira(direcao) {...}

Exemplo (2)
Trecho de programa que usa Manobrista: Em tempo de execuo passa implementao de Jegue e LandRover no lugar da implementao original de Veiculo (aproveita apenas a interface de Veiculo) Veiculo (...) (...) Manobrista mano Manobrista mano freia() {...} = new Manobrista (); acelera() {...} = new Manobrista (); Veiculo v1 = new Jegue(); Veiculo v1 = new Jegue(); Veiculo v2 = new LandRover(); Veiculo v2 = new LandRover(); mano.estaciona(v1); mano.estaciona(v1); mano.estaciona(v2); mano.estaciona(v2); (...) (...) Manobrista usa a classe Veiculo (e ignora a existncia de tipos especficos de Veiculo como Jegue e LandRover

Manobrista

vira(direcao) {...}

herdam interface
public void estaciona (Veiculo v) { ... v.freia(); ... }

Jegue
freia() {...} acelera() {...} vira(direcao) {...}

freia() {...} LandRover acelera() {...} vira(direcao) {...} freia() {...} acelera() {...} vira(direcao) {...}

Detalhes (1)
Pilha (referncias) Veiculo v1 0xffa903b7
03b7

Manobrista
public void estaciona (Veiculo v) { ... v.freia(); ... }

Heap (objetos) Jegue freia() {/* J */} acelera() {/* J */} vira() {/* J */}
6f55

Veiculo v2

0xffa96f55

LandRover freia() {/* R */} acelera() {/* R */} vira() {/* R */}

Veiculo v

null

Qual freia() ser executado quando o trecho abaixo for executado?


(...) Veiculo v1 = new Jegue(); mano.estaciona(v1); (...) ( mano do tipo Manobrista )

(referncia local do mtodo estaciona) Endereos (hipotticos) recebidos durante a execuo (inaccessveis ao programador)

a22c

Veiculo freia() {/* V */} acelera() {/* V */} vira() {/* V */}

...

10

Como funciona (3)


Veiculo v1 0xffa903b7
03b7

Manobrista
public void estaciona (Veiculo v) { ... v.freia(); ... }

Jegue freia() {/* J */} acelera() {/* J */} vira() {/* J */}

Veiculo v2

0xffa96f55
6f55

LandRover freia() {/* R */} acelera() {/* R */} vira() {/* R */}

Na chamada abaixo, Veiculo foi "substitudo" com Jegue. A implementao usada foi Jegue.freia()
(...) Veiculo v1 = new Jegue(); mano.estaciona(v1); (...) Veiculo v = v1

Veiculo v

0xffa903b7

Referncia de v1 foi copiada para referncia local v do mtodo Manobrista.estaciona()


Nos trechos de cdigo mostrados, este objeto nunca chegou a ser criado

a22c

Veiculo freia() {/* V */} acelera() {/* V */} vira() {/* V */}

...

Argumento do mtodo estaciona()

11

Conceitos abstratos
Como deve ser implementado freia() na classe Veiculo?
Faz sentido dizer como um veculo genrico deve frear? Como garantir que cada tipo especfico de veculo redefina a implementao de freia()?

O mtodo freia() um procedimento abstrato em Veiculo


Deve ser usada apenas a implementao das subclasses

E se no houver subclasses?
Como freia um Veiculo genrico? Com que se parece um Veiculo generico?

Concluso: no h como construir objetos do tipo Veiculo


um conceito genrico demais Mas timo como interface! Eu posso saber dirigir um Veiculo sem precisar saber dos detalhes de sua implementao

12

Mtodos e classes abstratos


Procedimentos genricos que tm a finalidade de servir apenas de interface so mtodos abstratos
declarados com o modificador abstract no tm corpo {}. Declarao termina em ";"
public abstract void freia(); public abstract float velocidade();

Mtodos abstratos no podem ser usados, apenas declarados


So usados atravs de uma subclasse que os implemente!

13

Classes abstratas
Uma classe pode ter mtodos concretos e abstratos
Se tiver um ou mais mtodo abstrato, classe no pode ser usada para criar objetos e precisa ter declarao abstract
public abstract class Veiculo { ... }

Objetos do tipo Veiculo no podem ser criados Subclasses de Veiculo podem ser criados desde que implementem TODOS os mtodos abstratos herdados Se a implementao for parcial, a subclasse tambm ter que ser declarada abstract

14

Classes abstratas (2)


Classes abstratas so criadas para serem estendidas Podem ter
mtodos concretos (usados atravs das subclasses) campos de dados (memria alocada na criao de objetos pelas suas subclasses) construtores (chamados via super() pelas subclasses)

Classes abstratas "puras"


no tm procedimentos no construtor (construtor vazio) no tm campos de dados (a no ser constantes estticas) todos os mtodos so abstratos

Classes abstratas "puras" podem ser definidas como "interfaces" para maior flexibilidade de uso

15

Template Method design pattern


Classe
void concreto() {

Algoritmos resultantes
Algoritmo
um() trs() dois() } Classe x = new ClasseConcretaUm() x.concreto()

Template Method

abstract void um(); abstract int dois(); abstract Object tres();

Mtodos abstratos
Classe x = new ClasseConcretaDois() x.concreto()

ClasseConcretaUm

ClasseConcretaDois

16

Template method: implementao


public abstract class Template { public abstract String link(String texto, String url); public String transform(String texto) { return texto; } public String templateMethod() { String msg = "Endereo: " + link("Empresa", "http://www.empresa.com"); return transform(msg); }

public class HTMLData extends Template { public String link(String texto, String url) { return "<a href='"+url+"'>"+texto+"</a>"; } public String transform(String texto) { return texto.toLowerCase(); } } public class XMLData extends Template { public String link(String texto, String url) { return "<endereco xlink:href='"+url+"'>"+texto+"</endereco>"; } }

17

Exerccio
1. Crie um novo projeto
Copie um build.xml genrico

2. Implemente os exemplos da aula:


Manobrista, Veiculo, Jegue e LandRover a) Implemente os mtodos com instrues de impresso, por exemplo:
public void freia() { System.out.println("Chamou Jegue.freia()"); }

b) Faa com que os mtodos de Veiculo sejam abstratos e refaa o exerccio

18

Upcasting
Tipos genricos (acima, na hierarquia) sempre podem receber objetos de suas subclasses: upcasting
Veiculo v = new Carro();

H garantia que subclasses possuem pelo menos os mesmos mtodos que a classe v s tem acesso "parte Veiculo" de Carro. Qualquer extenso (mtodos definidos em Carro) no faz parte da extenso e no pode ser usada pela referncia v.

19

Downcasting
Tipos especficos (abaixo, na hierarquia) no podem receber explicitamente seus objetos que foram declarados como referncias de suas superclasses: downcasting
Carro c = v; // no compila!

O cdigo acima no compila, apesar de v apontar para um Carro! preciso converter a referncia:
Carro c = (Carro) v;

E se v for Onibus e no Carro?

20

Upcasting e downcasting
Upcasting
sobe a hierarquia no requer cast
mtodos visveis na referncia v

Downcasting
desce a hierarquia requer operador de cast
Jegue j = (Jegue) v;
freia() acelera() vira() corre() morde()

Veiculo v = new Jegue();


Veiculo
freia() acelera() vira(direcao)

j v

Veiculo
freia() acelera() vira(direcao)

Jegue
acelera() vira(direcao) corre();

LandRover
diesel() tracao(tipo)

Jegue

LandRover
diesel() tracao(tipo)

mtodos visveis na referncia j

acelera() corre() morde()

21

ClassCastException
O downcasting explcito sempre aceito pelo compilador se o tipo da direita for superclasse do tipo da esquerda
Veiculo v = new Onibus(); Carro c = (Carro) v; // passa na compilao

Object, portanto, pode ser atribuda a qualquer tipo de referncia

Em tempo de execuo, a referncia ter que ser ligada ao objeto


Incompatibilidade provocar ClassCastException

Para evitar a exceo, use instanceof


if (v instanceof Carro) c = (Carro) v;

22

Herana Pura vs. Extenso


Herana pura: referncia tm acesso a todo o objeto
Veiculo
freia() acelera() vira(direcao)

Extenso: referncia apenas tem acesso parte definida na interface da classe base
Veiculo
freia() acelera() vira(direcao)

Referncia Veiculo no enxerga estes mtodos

Jegue
freia() acelera() vira(direcao)

LandRover
freia() acelera() vira(direcao)

Jegue
freia() acelera() vira(direcao) corre() morde()

LandRover
freia() acelera() vira(direcao) diesel() tracao(tipo)

Veiculo v = new Jegue(); v.freia() // freia o Jegue v.acelera(); // acelera o Jegue

Veiculo v = new Jegue(); v.corre() // ERRADO! v.acelera(); //OK

23

Ampliao da referncia
Uma referncia pode apontar para uma classe estendida, mas s pode usar mtodos e campos de sua interface Object
Para ter acesso total ao objeto que estende a interface original, preciso usar referncia que conhea toda sua interface pblica ERRADO: raio no faz parte da Exemplo interface de Object
class Circulo extends Object { class Circulo extends Object { public int raio; public int raio; public boolean equals(Object obj) { public boolean equals(Object obj) { if (this.raio == obj.raio) if (this.raio == obj.raio) return true; return true; verifica se obj return false; return false; realmente } } um Circulo } // CDIGO ERRADO! } // CDIGO ERRADO!
cria nova referncia que tem acesso a toda a interface de Circulo

equals()

Circulo raio equals()

class Circulo extends Object { class Circulo extends Object { public int raio; public int raio; public boolean equals(Object obj) { public boolean equals(Object obj) { if (obj instanceof Circulo) { if (obj instanceof Circulo) { Circulo k = (Circulo) obj; Circulo k = (Circulo) obj; if (this.raio == k.raio) if (this.raio == k.raio) return true; return true; } } return false; return false; Como k Circulo } } possui raio } }

24

Interfaces Java
Interface uma estrutura que representa uma classe abstrata "pura" em Java
No tm atributos de dados (s pode ter constantes estticas) No tem construtor Todos os mtodos so abstratos No declarada como class, mas como interface

Interfaces Java servem para fornecer polimorfismo sem herana


Uma classe pode "herdar" a interface (assinaturas dos mtodos) de vrias interfaces Java, mas apenas de uma classe Interfaces, portanto, oferecem um tipo de herana mltipla
25

Herana mltipla em C++


Em linguagens como C++, uma classe pode herdar mtodos de duas ou mais classes
A classe resultante pode ser usada no lugar das suas duas superclasses via upcasting Vantagem de herana mltipla: mais flexibilidade

Problema
Se duas classes A e B estenderem uma mesma classe Z e herdarem um mtodo x() e, uma classe C herdar de A e de B, qual ser a implementao de x() que C deve usar? A de A ou de B? Desvantagem de herana mltipla: ambigidade. Requer cdigo mais complexo para evitar problemas desse tipo
26

Herana mltipla em Java


Classe resultante combina todas as interfaces, mas s possui uma implementao: a da classe base <<interface>>
Animal come() respira()
<<interface>>

Cidadao vota() getRG()

<<interface>>

Contribuinte pagaIR() getCPF()

Empregado trabalha()
<<interface>>

Professor ensina()

Pessoa ensina() vota() getRG() trabalha() pagaIR() getCPF()

come() respira() ensina() vota() getRG() trabalha() pagaIR() getCPF() equals() toString() ...

Este objeto pode ser usado em qualquer lugar onde for aceito um Animal, um Professor, um Cidadao, um Empregado, um Contribuinte, um java.lang.Object

27

Exemplo
interface Empregado { void trabalha(); } interface Cidadao { void vota(); int getRG(); } interface Professor extends Empregado { void ensina(); } interface Contribuinte { boolean pagaIR(); long getCPF(); }

Todos os mtodos so implicitamente


public abstract

Quaisquer campos de dados tm que ser inicializadas e so implicitamente


static final (constantes)

Indicar public, static, abstract e final opcional Interface pode ser declarada public (default: package-private)

28

Exemplo (2)
public class Pessoa extends Animal implements Professor, Cidadao, Contribuinte { public public public public public public void ensina() { /* votar */ } void vota() { /* votar */ } int getRG(){ return 12345; } void trabalha() {} boolean pagaIR() { return false; } long getCPF() { return 1234567890; }

Palavra implements declara interfaces implementadas


Exige que cada um dos mtodos de cada interface sejam de fato implementados (na classe atual ou em alguma superclasse) Se alguma implementao estiver faltando, classe s compila se for declarada abstract

29

Uso de interfaces
public class Cidade { public void contrata(Professor p) { p.ensina(); p.trabalha(); } public void contrata(Empregado e) { public void cobraDe(Contribuinte c) public void registra(Cidadao c) public void alimenta(Animal a)

e.trabalha();} { c.pagaIR();} { c.getRG();} { a.come();}

public static void main (String[] args) { Pessoa joao = new Pessoa(); Cidade sp = new Cidade(); sp.contrata(joao); // considera Professor sp.contrata((Empregado)joao); // Empregado sp.cobraDe(joao); // considera Contribuinte sp.registra(joao); // considera Cidadao sp.alimenta(joao); // considera Animal } }

30

Concluso
Use interfaces sempre que possvel
Seu cdigo ser mais reutilizvel! Classes que j herdam de outra classe podem ser facilmente redesenhadas para implementar uma interface sem quebrar cdigo existente que a utilize

Planeje suas interfaces com muito cuidado


mais fcil evoluir classes concretas que interfaces No possvel acrescentar mtodos a uma interface depois que ela j estiver em uso (as classes que a implementam no compilaro mais!) Quando a evoluo for mais importante que a flexibilidade oferecido pelas interfaces, deve-se usar classes abstratas.
31

Exerccios
1. Implemente e execute o exemplo mostrado
Coloque texto em cada mtodo (um println() para mostrar que o mtodo foi chamado e descrever o que aconteceu) Faa experimentos deixando de implementar certos mtodos para ver as mensagens de erro obtidas

2. Implemente o exerccio do captulo 9 com interfaces


Mude o nome de RepositorioDados para RepositorioDadosMemoria Crie uma interface RepositorioDados implementada por RepositorioDadosMemoria Altere a linha em que o RepositorioDados construido na classe Biblioteca e teste a aplicao.
32

Curso J100: Java 2 Standard Edition


Reviso 17.0

1996-2003, Helder da Rocha (helder@acm.org)

argonavis.com.br
33

Você também pode gostar