Desenvolvimento OO com Java Classes abstratas e interfaces Vítor E. Silva Souza ([email protected]) http://www.inf.ufes.br/~vitorsouza Departamento de Informática Centro Tecnológico Universidade Federal do Espírito Santo Licençaparausoedistribuição • EsteobraestálicenciadacomumalicençaCreative Commons Atribuição-CompartilhaIgual 4.0Internacional; • Vocêtemodireitode: – Compartilhar:copiareredistribuiromaterialem qualquersuporteouformato – Adaptar:remixar,transformar,ecriarapartirdo materialparaqualquerfim,mesmoquecomercial. • Deacordocomostermosseguintes: – Atribuição:vocêdevedarocréditoapropriado,proverumlinkpara alicençaeindicarsemudançasforamfeitas.Vocêdevefazê-loem qualquercircunstânciarazoável,masdemaneiraalgumaquesugira aolicencianteaapoiarvocêouoseuuso; – CompartilhaIgual:sevocêremixar,transformar,oucriarapartirdo material,temdedistribuirassuascontribuiçõessobamesma licençaqueooriginal. Mais informações podem ser encontradas em: http://creativecommons.org/licenses/by-sa/4.0/ Abril2016 OO&Java- Classesabstrataseinterfaces 2 Conteúdodocurso • OqueéJava; • Variáveisprimitivase controledefluxo; • Orientaçãoaobjetos básica; • Umpoucodevetores; • Modificadoresdeacesso eatributosdeclasse; • Herança,reescritae polimorfismo; • Classesabstratas; • Interfaces; • Exceçõesecontrolede erros; • UtilitáriosdaAPIJava. EstesslidesforambaseadosnaapostiladocursoFJ-11:Javae OrientaçãoaObjetosdaCaelum ena apostila Programação Orientada aObjetos em Javadoprof.Flávio MiguelVarejão. Abril2016 OO&Java- Classesabstrataseinterfaces 3 Exemplo:umaplicativodedesenho Abril2016 OO&Java- Classesabstrataseinterfaces 4 Classesemétodosabstratos • Classes notopodahierarquiapodemsermuitogerais: – Oqueéumaforma? – Como sedesenhaumaforma? – Como seaumentaumaforma? • Taisoperaçõesnãofazemsentido.Queremosapenas definirqueelasexistam,masnãoimplementá-las; • Asolução:métodosabstratos. Abril2016 OO&Java- Classesabstrataseinterfaces 5 Classesemétodosabstratos • Umaclasse quepossuimétodosabstratosdeveser declaradacomoabstrata: abstract class Forma { public abstract void desenhar(); } class Circulo extends Forma { @Override public void desenhar() { System.out.println("Círculo"); } } Abril2016 OO&Java- Classesabstrataseinterfaces 6 Classesabstratas • Nãopermitemcriaçãodeinstâncias (objetos): – Ummétodoabstratonãopossuiimplementação, portantonãopodeserchamado. • Paraserútil,deveserestendida: – Suassubclasses devemimplementar ométodoou declararem-secomoabstratas. • Servemparadefinirinterfaces eproveralgumas implementações comuns. Polimorfismo! Abril2016 OO&Java- Classesabstrataseinterfaces 7 Construindoahierarquiadeformas Forma Decl. desenhar() Círculo Triângulo Retângulo Retângulo Decl. desenhar() Decl. desenhar() Decl. desenhar() Impl. desenhar() Impl. desenhar() Impl. desenhar() Quadrado Quadrado Decl. desenhar() Abril2016 OO&Java- Classesabstrataseinterfaces 8 Classesemétodosabstratos- Quiz Métodos estáticos podem ser abstratos? Não Construtores podem ser abstratos? Não Classes abstratas podem ter construtores? Sim Lembre-se: construtores são chamados pelas subclasses! Métodos abstratos podem ser privativos? Não Uma classe abstrata podem estender uma normal? Sim Posso ter uma classe abstrata sem nenhum método abstrato? Sim Abril2016 OO&Java- Classesabstrataseinterfaces 9 Classesabstratas(puras)econcretas // Classe abstrata pura. abstract class Forma { public abstract void desenhar(); public abstract void aumentar(int t); } // Classe abstrata. abstract class Poligono extends Forma { private int lados; public Poligono(int lados) { this.lados = lados; } public int getLados() { return lados; } public abstract void pintar(int cor); } Julho2013 DesenvolvimentoOOcomJava 10 Classesabstratas(puras)econcretas // Classe concreta. class Retangulo extends Poligono { public Retangulo() { super(4); } @Override public void desenhar() { System.out.println("Retangulo.desenhar"); } @Override public void aumentar(int t) { System.out.println("Retangulo.aumentar"); } @Override public void pintar(int cor) { System.out.println("Retangulo.pintar"); } } Julho2013 DesenvolvimentoOOcomJava 11 Interfaces • Umaclasseabstrata épura quando: – Possuimétodosabstratos; – Nãopossuimétodosconcretos; – Nãopossuiatributos (não-static). • Javaoferece apalavrareservadainterface: – Criaumaclasseabstrata pura; – Chamaremospelonomedeinterface; – Aoconversarcomoutrosprogramadores,cuidado paranãoconfundir com“interfacecomousuário”. Julho2013 DesenvolvimentoOOcomJava 12 Interfaces interface Forma { void desenhar(); void aumentar(int t); } abstract class Poligono implements Forma { private int lados; public Poligono(int lados) { this.lados = lados; } public int getLados() { return lados; } public abstract void pintar(int cor); } Julho2013 DesenvolvimentoOOcomJava 13 Interfaces class Linha implements Forma { private double x1, y1, x2, y2; @Override public void desenhar() { /* ... */ } @Override public void aumentar(int t) { /* ... */ } } Julho2013 DesenvolvimentoOOcomJava 14 Tudoé público na interface • Métodos definidosnainterfacesãoautomaticamente Exceção: default methods (Java 8) públicos eabstratos; • Atributos definidosnainterfacesãoautomaticamente públicos eestáticos. interface Forma { int x = 10; void desenhar(); } Definições equivalentes interface Forma { public static int x = 10; public abstract void desenhar(); } Por que isso existe? Só pra complicar a linguagem? Julho2013 DesenvolvimentoOOcomJava 15 Porisso,cuidadocomerros interface Forma { void desenhar(); void aumentar(int t); } class Linha implements Forma { // Erro: reduziu de público para privativo ao pacote! void desenhar() { /* ... */ } // Erro: reduziu de público para privativo! private void aumentar(int t) { /* ... */ } } Julho2013 DesenvolvimentoOOcomJava 16 Motivação Texto não é forma, OK! Como fica o método que carrega meu desenho do arquivo que eu salvei no HD? Abril2016 OO&Java- Classesabstrataseinterfaces 17 Não-solução 1 public class AplicativoDesenho { private static void desenhar(Forma[] fs) { for (int i = 0; i < fs.length; i++) fs[i].desenhar(); } Texto não é forma! Esse } método não serve… public class AplicativoDesenho { private static void desenhar(Forma[] fs) { for (int i = 0; i < fs.length; i++) fs[i].desenhar(); } private static void desenhar(Texto[] ts) { for (int i = 0; i < ts.length; i++) ts[i].escrever(); Já vimos, com polimorfismo, } que essa não é a solução… } Abril2016 OO&Java- Herança,reescritaepolimorfismo 18 Não-solução 2 Já sei! Abril2016 OO&Java- Classesabstrataseinterfaces 19 Solução:interfaces Abril2016 OO&Java- Classesabstrataseinterfaces 20 Solução:interfaces abstract class Forma implements Renderizavel { /* ... */ @Override public void renderizar() { desenhar(); } } class Texto implements Renderizavel { /* ... */ @Override public void renderizar() { escrever(); } } Julho2013 DesenvolvimentoOOcomJava 21 Solução:interfaces(alternativa) interface Forma extends Renderizavel { /* ... */ // As diferentes implementações de forma agora terão // que implementar renderizar() e não desenhar(). } class Texto implements Renderizavel { /* ... */ @Override public void renderizar() { escrever(); } } Julho2013 DesenvolvimentoOOcomJava 22 Solução:interfaces public class AplicativoDesenho { private static void desenhar(Renderizavel[] fs) { for (int i = 0; i < fs.length; i++) fs[i].renderizar(); } } • Opolimorfismo seamplia:maisummodo de referenciar umaforma:Renderizavel; • AplicativoDesenho não precisa saberaclasse realdo objeto,apenas que ele implementa ainterface; – Seimplementa ainterface,ele implementa ométodo renderizar()! • Novas classes podem ser renderizáveis! Abril2016 OO&Java- Herança,reescritaepolimorfismo 23 Interface=contrato • Renderizavel definequetodas asclasses quea implementamsaibam serenderizar() – “oque”; – Aimplementação define“ocomo”; • Defineumcontrato:“quemdesejarserrenderizável precisasaberserenderizar()”; – Aclasse quequiser,assina ocontrato ese responsabilizaacumpri-lo; • Programevoltadoainterfaces enãoaimplementações (massemexageros). Interfaces não são apenas um cabeçalho .h como em C! Abril2016 OO&Java- Classesabstrataseinterfaces 24 Herança múltipla em Java Pode isso, Arnaldo? Abril2016 OO&Java- Classesabstrataseinterfaces 25 Herança múltipla em Java A regra é clara… Abril2016 OO&Java- Classesabstrataseinterfaces 26 Herança múltipla em Java class CaixaDeTexto extends Texto implements Forma { private Retangulo caixa; /* ... */ public CaixaDeTexto() { // Parâmetros foram omitidos para simplificar... caixa = new Retangulo(); } public void renderizar() { // Desenha a caixa. caixa.renderizar(); // Escreve o texto. escrever(); } } Julho2013 DesenvolvimentoOOcomJava 27 AinterfaceComparable • Umexemplo deinterfacenaAPIJavaéainterface Comparable; • Defineométodo compareTo(Object obj): – Compara oobjetoatual(this)comoobjeto informado(obj); – Retorna0 sethis =obj; – Retornaumnúmeronegativosethis <obj; – Retornaumnúmeropositivosethis >obj. • Métodosgenéricos autilizamparaordenar coleçõesde elementos. Julho2013 DesenvolvimentoOOcomJava 28 AinterfaceComparable class Valor implements Comparable { int valor; public Valor(int v) { valor = v; } @Override public int compareTo(Object obj) { return valor - ((Valor)obj).valor; } @Override public String toString() { return "" + valor; } } Julho2013 DesenvolvimentoOOcomJava 29 AinterfaceComparable public class Teste { static void imprimir(Object[] vetor) { for (int i = 0; i < vetor.length; i++) System.out.print(vetor[i] + "; "); System.out.println(); } public static void main(String[] args) { Valor[] vetor = new Valor[] { new Valor(10), new Valor(3), new Valor(15), new Valor(7) }; imprimir(vetor); // 10; 3; 15; 7; Arrays.sort(vetor); imprimir(vetor); // 3; 7; 10; 15; } } Julho2013 DesenvolvimentoOOcomJava 30 DesenvolvimentoOOcomJava– Classesabstrataseinterfaces OMECANISMODERTTI Abril2016 OO&Java- Classesabstrataseinterfaces 31 Polimorfismoeextensão • Compolimorfismo,podemosesquecer aclassedeum objetoetrabalharcomasuperclasse: – Ainterface deambaséamesma; – Aamarraçãodinâmica garantequeométododa classecorreta seráexecutado. • Oqueaconteceseasubclasseestende asuperclasse (adiciona maisfuncionalidade)? • Seasuperclassenãopossuiaquelafuncionalidade,não podemoschamá-la! Julho2013 DesenvolvimentoOOcomJava 32 Polimorfismoeextensão interface Animal { void comer(); } class Cachorro implements Animal { @Override public void comer() { System.out.println("Comendo um osso..."); } public void latir() { System.out.println("Au Au!"); } } class Gato implements Animal { @Override public void comer() { System.out.println("Comendo um peixe..."); } public void miar() { System.out.println("Miau!"); } DesenvolvimentoOOcomJava } Julho2013 33 Polimorfismoeextensão public class Teste { public static void main(String[] args) { Animal[] vet = new Animal[] { new Cachorro(), new Gato(), new Gato(), new Cachorro() }; for (int i = 0; i < vet.length; i++) { vet[i].comer(); // Erro: vet[i].latir(); } } } #comofas? Julho2013 DesenvolvimentoOOcomJava 34 Estreitamento(downcast) • Precisamosrelembrar aclasseespecíficadoobjetopara chamarmosmétodos quenãoestãonainterfaceda superclasse; • Paraissofaremosestreitamento: Ampliação (upcast) Estreitamento (downcast) int para long long para int float para double double para float Cachorro para Animal Animal para Cachorro Gato para Animal Animal para Gato Julho2013 DesenvolvimentoOOcomJava 35 Upcast vs.downcast • Ampliaçãoéautomática elivredeerros: – Aclassebase nãopodepossuirumainterfacemaior doqueaclassederivada; – Nãoénecessárioexplicitar oupcast. • Estreitamentoémanual epodecausarerros: – Aclassebasepodetervárias subclassesevocêestá convertendoparaaclasseerrada; – Énecessárioexplicitar odowncast; – Podelançarumerro (ClassCastException); – Podehaverperda deinformação(tiposprimitivos). Julho2013 DesenvolvimentoOOcomJava 36 Upcast vs.downcast public class Teste { public static void main(String[] args) { Animal a = new Cachorro(); Cachorro c = (Cachorro)a; Upcast c.latir(); // Forma resumida: a = new Gato(); ((Gato)a).miar(); Downcast } } Julho2013 DesenvolvimentoOOcomJava 37 RTTI:Run-TimeType Identification • Omecanismoqueverifica otipo deumobjetoem tempodeexecução chama-seRTTI; • RTTI=Run-TimeType Identification ouIdentificaçãode TiposemTempodeExecução; • Estemecanismogarantequeasconversões sãosempre seguras; • Nãopermitequeumobjetosejaconvertido parauma classeinválida: – Fora dahierarquia:errodecompilação; – Dentro dahierarquia:errodeexecução. Julho2013 DesenvolvimentoOOcomJava 38 RTTI:Run-TimeType Identification public class Teste { public static void main(String[] args) { Animal a = new Cachorro(); // Sem erro nenhum: Cachorro c = (Cachorro)a; // Erro de execução (ClassCastException): Gato g = (Gato)a; // Erro de compilação: String s = (String)a; } } Julho2013 DesenvolvimentoOOcomJava 39 Ooperadorinstanceof • OmecanismodeRTTIpermitequevocêconsulte seum objeto édeumadeterminadaclasse; • Operadorinstanceof: – Sintaxe: <objeto> instanceof <Classe> – Retornatrue seoobjetoforinstância (diretaou indireta)daclasse especificada; – Retornafalse casocontrário. Julho2013 DesenvolvimentoOOcomJava 40 Ooperadorinstanceof public class Teste { public static void main(String[] args) { Animal[] vet = new Animal[] { new Cachorro(), new Gato(), new Gato(), new Cachorro() }; for (int i = 0; i < vet.length; i++) { if (vet[i] instanceof Cachorro) ((Cachorro)vet[i]).latir(); else if (vet[i] instanceof Gato) ((Gato)vet[i]).miar(); } } } Julho2013 DesenvolvimentoOOcomJava 41 Ousodeinstanceof deveserraro • Nãoéumaboapráticausarinstanceof: – Usepolimorfismo; – Useclassesgenéricas (veremosadiante). • Useinstanceof apenasquandonãoháoutrasolução. Julho2013 DesenvolvimentoOOcomJava 42 Trocandoinstanceof porpolimorfismo interface Animal { void comer(); void falar(); } class Cachorro extends Animal { @Override public void comer() { /* ... */ } @Override public void falar() { /* ... */ } } class Gato extends Animal { @Override public void comer() { /* ... */ } @Override public void falar() { /* ... */ } } Julho2013 DesenvolvimentoOOcomJava 43 Trocandoinstanceof porgenéricos public class Teste { public static void main(String[] args) { Cachorro c; List lista = new ArrayList(); lista.add(new Cachorro()); Object o = lista.get(0); if (o instanceof Cachorro) c = (Cachorro)o; // Com genéricos. List<Cachorro> listaGen; listaGen = new ArrayList<Cachorro>(); listaGen.add(new Cachorro()); c = listaGen.get(0); } } Julho2013 DesenvolvimentoOOcomJava 44 Exercitaréfundamental • ApostilaFJ-11daCaelum – ClassesAbstratas: – Seção9.6,página121(conta corrente); – Seção9.7,página123(desafios); • ApostilaFJ-11daCaelum – Interfaces: – Seção 10.5,página 134(formas,conta corrente); – Seção 10.6,página 138(exercícios avançados); – Seção 10.7,página 139(discussão). Abril2016 OO&Java- Classesabstrataseinterfaces 45 http://nemo.inf.ufes.br/