Baixe o app para aproveitar ainda mais
Prévia do material em texto
INTERFACES Thaís Alves Burity Rocha Agenda Introdução Interface Exemplo da API de Java: Classe Arrays, Classe Collections e Interface Comparable Implementação de múltiplas interfaces Utilidade Relembrando… Polimorfismo significa que uma chamada de método pode ser executada de várias formas Um contrato ou interface de acesso, várias implementações Onde ContaAbstrata é aceita, Conta, Poupanca, ContaBonificada e ContaImposto também é ContaAbstrata creditar() debitar() transferir() Conta Poupanca ContaBonificada ContaImposto Usuário do objeto enxerga apenas esse “contrato” Polimorfismo Achar o método certo a ser chamado para um objeto em particular chama-se dynamic binding (ligação dinâmica) O tipo real do objeto é identificado em tempo de execução Portanto, a versão do método a ser executada também é definida em tempo de execução Já sabemos disso! Interface x Implementação O contrato separa a interface de acesso da implementação A classe base define uma interface comum Não precisa dizer como vai ser feito Diz apenas as operação suportadas, especificando suas entradas e saídas É possível debitar, creditar e transferir de uma conta ContaAbstrata creditar() debitar() transferir() Usando Herança na Definição de Contratos Subclasses de ContaAbstrata herdam todos os seus métodos (não-private) Significa que é herdado o tipo da superclasse e também sua implementação Ao herdar, a subclasse pode substituir alguns métodos ContaBonificada sobrescreveu creditar Usando classes/métodos abstratos é possível exigir a sobrescrita de métodos É o caso do método debitar Usando Herança na Definição de Contratos Em se tratando de conta bancária, faz sentido haver herança Comportamentos comuns podem ser reusados Comportamentos distintos podem ser ajustados Sobrescrita de métodos (abstratos e não-abstratos) Há polimorfismo Definição de Contrato Sem Herança Em outros casos, é desejável haver um contrato, mas não faz sentido reusar comportamento Contrato polimorfismo Exemplo: Repositório de dados Contrato: Operações de CRUD Diferentes formas de armazenamento Memória (volátil): Vetor, ArrayList… Disco (permanente): Arquivos Banco de Dados (permanente, facilita a consulta dos dados) Definição de Contrato Sem Herança: Uma Possível Solução public abstract class RepositorioContas { public abstract void adicionar(ContaAbstrata conta); public abstract void remover(ContaAbstrata conta); public abstract void atualizar(ContaAbstrata conta); public abstract ContaAbstrata consultar(ContaAbstrata conta); public abstract ContaAbstrata consultar(String numero); } Subclasses: RepositorioContasVetor, RepositorioContasArrayList, RepositorioContasArquivo, RepositorioContasBD Na prática, só está havendo herança de tipo Interface Semelhante à uma classe Serve para definir contratos “sem haver herança” Polimorfismo Todos os métodos são implicitamente abstract e public É declarada com a palavra-chave interface Não pode ser instanciada Não possui construtor Foi feita para ser implementada: Palavra-chave implements Interface: Exemplo de Declaração É redundante declarar métodos como public e abstract public interface IRepositorioContas { public abstract void adicionar(ContaAbstrata conta); void remover(ContaAbstrata conta); void atualizar(ContaAbstrata conta); ContaAbstrata consultar(ContaAbstrata conta); ContaAbstrata consultar(String numero); } Convenção: Começar nome de interface com I Interface Introduz os conceitos de: Supertipo: Definido pela interface Subtipo: Definido pela classe que implementa a interface Subtipos devem implementar todos os métodos definidos na interface Caso contrário, devem ser declarados como classes abstratas Interface: Exemplo de Implementação public class RepositorioContasArrayList implements IRepositorioContas { private ArrayList<ContaAbstrata> array; public RepositorioContasArrayList(){ array = new ArrayList<ContaAbstrata>(); } public void adicionar(ContaAbstrata conta){ int indice = array.indexOf(conta); if(indice == -1) array.add(conta); else{ System.out.println("Não é possível adicionar uma conta igual a outra já existente!"); } } //demais métodos aqui } Sobrescrita Interface: Exemplo de Implementação public class RepositorioContasVetor implements IRepositorioContas{ private ContaAbstrata[] contas; private int indice; public static final int TAMANHO = 5; public RepositorioContasVetor(){ contas = new ContaAbstrata[TAMANHO]; } public void adicionar(ContaAbstrata conta){ int i = this.procurarIndice(conta.getNumero()); if(i != -1){ System.out.println("A conta já existe."); } else if(indice>=0 && indice<contas.length && contas[indice]==null){ contas[indice] = conta; this.atualizarIndice(); }else{ System.out.println("O repositório está cheio."); } } //demais métodos aqui } Sobrescrita Interface Métodos não podem ser static Atributos são implicitamente constantes (static e final) Modificadores de acesso são os mesmos de classes default public Interface e Constantes Classes que implementam uma interface herdam todas as constantes definidas na interface Podem usá-las como se fossem da própria classe Classes que não implementam uma dada interface podem usar suas constantes Como qualquer membro static: <nome da interface>.<nome da constante> Interface Não pode ser instanciada, mas pode ser referenciada IRepositorioContas rep = new RepositorioContasVetor(); ContaAbstrata conta = new Conta(); rep.adicionar(conta); conta = new ContaBonificada(); rep.adicionar(conta); E se a gente quiser usar outro repositório? Classe java.util.Arrays Provê métodos estáticos para manipulação de vetores de qualquer tipo Ordenação de vetor: void Arrays.sort(vetor) Vetor de tipo primitivo: Ordenação natural Vetor de objetos: A classe do objeto deve implementar a interface Comparable (java.lang.Comparable) Método: public int compareTo(Object obj) Lógica: Dada a chamada a.compareTo(b) Retornar um inteiro <0, se a for “menor” que b Retornar um inteiro >0, se a for “maior” que b Retornar zero se a e b forem iguais Classe java.util.Arrays: Exemplo Ordenar vetor de ContaAbstrata pelo saldo public abstract class ContaAbstrata implements Comparable { ... public int compareTo(Object obj){ ContaAbstrata conta = (ContaAbstrata) obj; if(this.saldo>conta.getSaldo()) return 1; else if(this.saldo<conta.getSaldo())return -1; else return 0; } } Classe java.util.Arrays: Exemplo Agora a chamada para o método de ordenação O ideal seria ter um método de ordenação no repositório de contas ContaAbstrata[] vetor = repositorioConta.getContas(); Arrays.sort(vetor); for(ContaAbstrata c: vetor){ System.out.println(c); } Classe java.util.Collections É possível ordenar um ArrayList usando o método sort da classe java.util.Collections Também exige que a classe dos objetos no ArrayList implemente a interface Comparable //onde tinha ordenação de vetor Arrays.sort(vetor); //substituir por ordenação de ArrayList Collections.sort(arrayList); Implementação de Múltiplas Interfaces Uma classe pode implementar mais de uma interface Mecanismo simplificado de herança múltipla em Java public class RadioRelogio implements Relogio, Radio { public String getHoras(){ ...} public void ligar(){ ... } public void desligar(){ ... } public void trocarEstacao(int frequencia){ ... } } public interface Relogio{ String getHoras(); } public interface Radio{ void ligar(); void desligar(); void trocarEstacao(int frequencia); } Implementação de Múltiplas Interfaces Se as interfaces possuem uma constante com mesmo nome, a classe não irá compilar O compilador não saberá qual o valor a ser utilizado Não há problema se as interfaces possuem métodos com mesma assinatura A classe só precisará sobrescrever o método uma vez Interfaces: Utilidade O principal benefício do uso de interface é o polimorfismo e, por consequência, flexibilidade Usar interface como argumento e tipo de retorno garante que, na prática, poderá ser usado qualquer tipo que implemente essa interface Interfaces definem funções/papéis que a classe pode desempenhar Interfaces: Utilidade Classes em diferentes hierarquias podem implementar as mesmas interfaces Ocultação de informação (information hiding) Decompor o sistema em módulos Cada modulo contém uma parte interna e uma parte externa A parte interna é escondida de outros módulos A parte externa é o contrato, o que os outros módulos enxergam Quando criar uma classe, subclasse, classe abstrata ou interface? Não use herança quando a nova classe não passar no teste É-UM com nenhuma outra Use herança quando tiver que criar uma versão mais específica de uma classe e precisar sobrepor ou adicionar novos comportamentos Quando criar uma classe, subclasse, classe abstrata ou interface? Use uma classe abstrata quando quiser definir um contrato para um grupo de subclasses e tiver algum código para ser reusado entre elas Use uma classe abstrata quando quiser garantir que ninguém possa criar objetos da classe Quando criar uma classe, subclasse, classe abstrata ou interface? Use uma interface quando quiser definir uma função que outras classes possam desempenhar, independente de hierarquia de herança Lembre-se: Contratos estão menos vulneráveis à mudanças, pois não há implementação
Compartilhar