Java Básico Classes Abstratas e Interfaces Marco Antonio, Arquiteto de Software – TJDF...

Preview:

Citation preview

Java Básico

Classes Abstratas e Interfaces

Marco Antonio,

Arquiteto de Software – TJDF

ma@marcoreis.netAtualizado em Novembro/2008

Classe abstrata

Recurso avançado da OO

Não pode ser instanciada

Deve ser instanciada através de uma subclasse concreta

Permite modelar com mais precisão as regras de negócio

Refinamento do projeto

O programador fica obrigado a utilizar as regras definidas pelo projetista

Pode ter a implementação para os métodos

Interface

Funciona como um contrato

Não pode ser instanciada

Pode ser instanciada através de uma classe que a implemente

Obriga o programador a usar os métodos já definidos

Não tem implementação, apenas a assinatura dos métodos

Muito útil para diminuir o acoplamento entre os vários módulos do sistema

Classe abstrata x Interface

Não existe uma regra geral que defina quando usar classes abstratas ou interfaces

• O nível de refinamento deve ser definido antes da implementação, o que diminui o risco de entrar num ciclo de refinamentos sem fim

Dica

Quando haja a possibilidade de reutilização de código, prefira classe abstrata

Se o código reaproveitado é muito pequeno, talvez seja mais interessante uma interface

Exemplo de classe abstrata

Vamos utilizar a classe Musico para ilustrar o conceito de classe abstrata

Baterista, Guitarrista e Baixista são nossas outras classes do modelo

Analise o relacionamento entre elas

Musico

package com.javabasico.classesabstratas;

public abstract class Musico {

public abstract String getNomeDoInstrumento();

public void afinarInstrumento() {

System.out.println("Estou afinando o/a " + getNomeDoInstrumento());

}

}

Baixista

package com.javabasico.classesabstratas;

public class Baixista extends Musico {

public String getNomeDoInstrumento() {

return "Baixo";

}

}

Guitarrista

package com.javabasico.classesabstratas;

public class Guitarrista extends Musico {

public String getNomeDoInstrumento() {

return "Guitarra";

}

}

Baterista

package com.javabasico.classesabstratas;

public class Baterista extends Musico {

public String getNomeDoInstrumento() {

return "Bateria";

}

}

TesteDoMusico

package com.javabasico.classesabstratas;

public class TesteDoMusico {

public static void main(String[] args) {

Musico baixista = new Baixista();

baixista.afinarInstrumento();

Musico batera = new Baterista();

batera.afinarInstrumento();

Musico guitarrista = new Guitarrista();

guitarrista.afinarInstrumento();

}

}

Exemplo de interface

• Vamos utilizar a interface Veiculo no nosso exemplo

• Além desta, também teremos Carro, Moto e Caminhao

Veiculo

package com.javabasico.interfaces;

public interface Veiculo {

public int getQuantidadeDePneus();

public boolean isVeiculoDePasseio();

public int getPotencia();

}

Carro

package com.javabasico.interfaces;

public class Carro implements Veiculo {

public int getQuantidadeDePneus() {

return 4;

}

public boolean isVeiculoDePasseio() {

return true;

}

public int getPotencia() {

return 80;

}

}

Moto

package com.javabasico.interfaces;

public class Moto implements Veiculo{

public int getQuantidadeDePneus() {

return 2;

}

public boolean isVeiculoDePasseio() {

return true;

}

public int getPotencia() {

return 30;

}

}

Caminhao

package com.javabasico.interfaces;

public class Caminhao implements Veiculo {

public int getQuantidadeDePneus() {

return 6;

}

public boolean isVeiculoDePasseio() {

return false;

}

public int getPotencia() {

return 130;

}

}

TesteDoVeiculo

package com.javabasico.interfaces;

public class TesteDoVeiculo {

public static void main(String[] args) {

Veiculo minhaMoto = new Veiculo();

}

}

Qual o problema?

Qual o problema da classe de teste?• Simples: uma interface não pode ser instanciada

– new Veiculo();• Não existe, no modelo anterior, um objeto do tipo Veiculo (o veículo é apenas conceitual)

• Existem apenas Carros, Motos e Caminhoes• Toda interface deve ter uma classe que a implemente, caso contrário, não faz sentido esse tipo de refinamento

TesteDoVeiculopackage com.javabasico.interfaces;

public class TesteDoVeiculo {

public static void main(String[] args) {

Veiculo minhaMoto = new Moto();

System.out.println("Quantidade de cavalos da moto:" + minhaMoto.getPotencia());

Veiculo meuCarro = new Carro();

System.out.println("Quantidade de pneus do carro: " + meuCarro.getQuantidadeDePneus());

Veiculo meuCaminhao = new Caminhao();

System.out.println("O caminhão é veículo de passeio? " + meuCaminhao.isVeiculoDePasseio());

}

}

Exemplo Web

• Vamos imaginar a seguinte hierarquia de classes:– ControleHTML

• CaixaDeTexto• CaixaDeChecagem• Outros componentes HTML

• O ControleHTML terá os atributos comuns a todos os controles web (nome, valor) e deverá ser definido como abstract, porque o método getCodigoHTML não tem implementação.

• No momento de gerar a página HTML iremos instanciar o componente concreto (caixas de texto, comboboxes, caixas de checagem, botoes, etc).

• Para cada componente, teremos uma saída diferente para o método getCodigoHTML.

ControleHTMLpackage com.javabasico.classesabstratas;

public abstract class ControleHTML {

private String nome;

private String valor;

public String getNome() {

return nome;

}

public void setNome(String nome) {

this.nome = nome;

}

public String getValor() {

return valor;

}

public void setValor(String valor) {

this.valor = valor;

}

public abstract String getCodigoHTML();

}

CaixaDeChecagem

package com.javabasico.classesabstratas;

public class CaixaDeChecagem extends ControleHTML {

public String getCodigoHTML() {

StringBuilder html = new StringBuilder();

html.append("<input type=\"checkbox\"");

html.append("name=");

html.append(getNome());

html.append("\"value=\"");

html.append(getValor());

html.append("\">");

return html.toString();

}

}

CaixaDeTexto

package com.javabasico.classesabstratas;

public class CaixaDeTexto extends ControleHTML { public String getCodigoHTML() { StringBuilder html = new StringBuilder(); html.append("<input type=\"text\""); html.append("name=\""); html.append(getNome()); html.append("\" value=\""); html.append(getValor()); html.append("\" >"); return html.toString(); }}

PaginaWeb

package com.javabasico.classesabstratas;

public class PaginaWeb { public static void main(String[] args) { ControleHTML caixaDeTexto = new CaixaDeTexto(); caixaDeTexto.setNome("txtNome"); caixaDeTexto.setValor("Marco"); ControleHTML caixaDeChecagem = new CaixaDeChecagem(); caixaDeChecagem.setNome("chkUsuarioCadastrado"); caixaDeChecagem.setValor("1"); System.out.println(caixaDeTexto.getCodigoHTML()); System.out.println(caixaDeChecagem.getCodigoHTML()); }}

Exemplo com interfaces

• No próximo exemplo teremos as formas geométricas conforme a hierarquia:– FormaGeometrica

• Triangulo• Quadrado• Retangulo• Etc...

• A interface principal terá os métodos desenhar e apagar, claro, sem a implementação, que será feita nas classes a seguir.

FormaGeometrica

package com.javabasico.interfaces;

public interface FormaGeometrica {

public void desenhar();

public void apagar();

}

Triangulo

package com.javabasico.interfaces;

public class Triangulo implements FormaGeometrica {

public void apagar() {

System.out.println("Estou apagando o triângulo...");

}

public void desenhar() {

System.out.println("Estou desenhando um triângulo...");

}

}

Quadrado

package com.javabasico.interfaces;

public class Quadrado implements FormaGeometrica {

public void apagar() {

System.out.println("Estou apagando o quadrado.");

}

public void desenhar() {

System.out.println("Estou desenhando um quadrado.");

}

}

TesteFormasGeometricas

package com.javabasico.interfaces;

public class TesteFormasGeometricas { public static void main(String[] args) { FormaGeometrica forma = new Triangulo(); forma.desenhar(); forma.apagar(); }}

Ligação dinâmica

• Devemos observar que criamos um objeto do tipo FormaGeometrica e que dinamicamente a linguagem trocou para a classe Triangulo.

• Esse comportamento é verificado nas interfaces e nas classes.

TesteFormasGeometricas

package com.javabasico.interfaces;

public class TesteFormasGeometricas { public static void main(String[] args) { FormaGeometrica forma = new Triangulo(); forma.desenhar(); forma.apagar(); // forma = new Quadrado(); forma.desenhar(); forma.apagar(); }}

Sua vez

• Crie mais duas formas geométicas e teste tudo na nossa classe.

Curiosidades

• O mesmo objeto (forma) teve dois comportamentos diferentes, executando métodos em classes diferentes.

• No próximo exemplo teremos mais uma curiosidade, passando uma interface como parâmetro.

• O SoftwareGrafico irá aceitar somente implementações de FormaGeometrica.

• Para testar, crie a classe Elipse com os mesmos métodos da FormaGeometrica, mas não implemente a interface. Tente passá-la como parâmetro. O que acontece?

SoftwareGrafico

package com.javabasico.interfaces;

public class SoftwareGrafico { public void adicionarForma(FormaGeometrica forma) { forma.desenhar(); }

public void removerForma(FormaGeometrica forma) { forma.apagar(); }}

TesteSoftwareGrafico

package com.javabasico.interfaces;

public class TesteSoftwareGrafico {

public static void main(String[] args) {

SoftwareGrafico photoshop = new SoftwareGrafico();

Quadrado umQuadrado = new Quadrado();

photoshop.adicionarForma(umQuadrado);

//

Triangulo umTriangulo = new Triangulo();

photoshop.adicionarForma(umTriangulo);

//

photoshop.removerForma(umTriangulo);

photoshop.removerForma(umQuadrado);

}

}

Dúvidas?

Impressora

package com.javabasico.classesabstratas;

public interface Impressora {

void imprimir();

void imprimir(String texto);

}

Lexmark

package com.javabasico.classesabstratas;

public class Lexmark implements Impressora {

@Override

public void imprimir() {

System.out.println("Estou imprimindo na Lexmark...");

}

@Override

public void imprimir(String texto) {

System.out.println("Estou imprimindo o texto: " + texto + "na Lexmark.");

}

}

Teste

package com.javabasico.classesabstratas;

public class TesteDaImpressora {

public static void main(String args[]) {

Impressora l = new Lexmark();

l.imprimir();

l.imprimir("Alguma coisa");

}

}

Classes Anônimas

package com.javabasico.classesabstratas;

public class TesteImpressoraAnonima {

public static void main(String[] args) {

Impressora i = new Impressora() {

@Override

public void imprimir() {

System.out.println("Imprimindo pela classe anonima");

}

@Override

public void imprimir(String texto) {

System.out.println("Classe anonima: " + texto);

}

};

i.imprimir();

i.imprimir("Algum texto");

}

}

Exercício

• Cria uma classe para representar as peças de um veículo. Essa deverá ser uma classe genérica e abstrata (ou interface).

• Em seguida crie as peças, que serão subclasses (porta, vidro, lanterna, retrovisor).

• Por fim, crie uma classe de teste e monte um carro com essas peças.

Recommended