Baixe o app para aproveitar ainda mais
Prévia do material em texto
1 FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADOS EM CIÊNCIA DA COMPUTAÇÃO E SISTEMAS DE INFORMAÇÃO E TECNOLOGIA EM ANÁLISE E DESENVOLVIMENTO DE SISTEMAS Linguagem de Programação I – SEMANA 10 TEORIA: INTERFACES Nossos objetivos nesta aula são: Conhecer o conceito de interfaces e as diferenças entre classes abstratas e interface, além de implementá-los em Java; Escrever uma interface em Java; Compreender como o recurso de Interface pode reduzir o acoplamento entre classes; Conhecer a classe Collections do Java; Conhecer a interface Comparable da API do Java. A referência para esta aula é o Capítulo 9 (Interfaces e Polimorfismo) e Capítulo 14.18 (Classificação e Pesquisa – Classificação de dados reais) do nosso livro-texto: Horstmann, C. Conceitos de Computação com Java. 5.ed. Porto Alegre: Bookman, 2009. Não deixem de ler estes capítulos após a aula de hoje! INTERFACES Até este momento, nosso sistema de contas bancárias é controlado apenas por uma única classe Bank. Queremos agora, disponibilizar o acesso às contas também através de um caixa eletrônico (ATM). O caixa eletrônico deverá permitir o acesso às seguintes funcionalidades de uma conta bancária: o consulta de saldo (getBalance) o depósitos (deposit) o retiradas (withdraw) 2 O acesso a estas funcionalidades num caixa eletrônico deverá ser feito da mesma maneira que num banco, através de uma interface comum. Uma interface define um contrato público que deve ser seguido por todas as classes que a implementem. Neste contrato, especificamos as assinaturas dos métodos que vem ser seguidos pelas classes, além de possíveis constantes compartilhadas por elas. Uma interface permite reduzir o nível de acoplamento entre classes, uma vez que não dependemos de herança ou associações para ficarmos de acordo com um mesmo contrato. Para definirmos uma interface em Java, utilizamos a palavra reservada interface. No exemplo abaixo, temos uma interface para as funcionalidades de contas bancárias que definimos antes: public interface BankAccountOperation { public double getBalance(int accountNumber); // saldo de uma determinada conta public void deposit(int accountNumber,double value); // depósito em uma determinada conta public void withdraw(int accountNumber,double value); // retirada de uma determinada conta } Para implementarmos uma interface, utilizamos a palavra implements (como no exemplo da classe Bank, abaixo). Uma mesma classe pode Java pode implementar várias interfaces. class Bank implements BankAccountOperation { ... } Uma vez que uma classe declare implementar uma interface, ela precisa implementar todos os métodos desta interface. EXERCÍCIO TUTORIADO Implemente a interface BankAccountOperation na classe Bank: class Bank implements BankAccountOperation { } 3 Vamos, agora, à implementação da classe que irá representar o nosso caixa eletrônico (ATM). ATM também deverá implementar a interface BankAccountOperation e acessar um determinado banco para efetivar as operações. Além disto, todas as operações realizadas num caixa eletrônico terão uma taxa fixa, cujo valor deverá ser retirado do saldo no momento da operação. EXERCÍCIO TUTORIADO Implemente a classe ATM, cuja estrutura básica é mostrada abaixo: class ATM implements BankAccountOperation { private Bank b; // banco vinculado ao caixa eletrônico private double fee; // taxa cobrada pela uso do caixa eletrônico public ATM (Bank b, double fee) {. .. } } 4 MÉTODOS GENÉRICOS Observe que, tanto a classe Bank quanto a classe ATM, implementam a mesma interface, porém de maneira distinta. Além de permitir a redução do acoplamento entre classes, interfaces também permitem definir métodos genéricos. Por exemplo: static double doGetBalance (BankAccountOperation bao, int accountNumber){ return bao.getBalance (accountNumber); } Quando criamos uma variável do tipo BankAccountOperation, estamos criando uma referência para qualquer objeto de uma classe que implementa BankAccountOperation, direta ou indiretamente. Não sabemos previamente que o objeto bao está apontando exatamente, isto fornece flexibilidade. Permite que utilizemos tanto objeto do tipo Bank quanto ATM como parâmetros para o objeto bao, uma vez que implementamos a mesma interface BankAccountOperation nas duas classes. Assim, podemos fazer: Bank b = new Bank(...); ATM atm = new ATM(...); System.out.println(doGetBalance(b,100)); System.out.println(doGetBalance(atm,100)); Lembrar que a interface define o que todos os objetos vão realizar, no caso, uma operação bancária de saque, depósito e verificação de saldo (o que ele faz), enquanto a implementação define como exatamente será feito (como ele faz). A maneira como os objetos se comunicam em um sistema orientado a objetos é mais importante do que como eles executam. O que um objeto faz é mais importante do que como ele faz. Seguir essa orientação, faz com que os sistemas sejam fáceis de manter e de modificar. 5 EXERCÍCIO TUTORIADO Crie uma interface na Linguagem Java para representar forma geométrica. Por padrão, para qualquer forma geométrica, tem uma fórmula matemática para calcular a sua área. Leve isso em consideração na hora de criar a sua interface. Após isso, crie as classes: Circulo e Retangulo. Todas essas classes devem implementar a interface da forma geométrica. Para tanto, considere que: – Retângulo: area = largura * altura – Círculo: area = ∏ * raio * raio 6 MÉTODOS ABSTRATOS x INTERFACES Se observamos o que estudamos até agora, veremos que temos duas maneiras de definir somente a assinatura de um método: o métodos abstratos o interfaces Porém, a implementação destas duas assinaturas ocorre de maneira distinta: o métodos abstratos: precisamos estender a classe que contém o método abstrato, ou seja, dependemos de uma herança para que isto possa ser feito. Isto, além de aumentar o acoplamento entre classes, ainda impõe o fato de que vamos herdar parte (ou o todo) de uma hierarquia de classes. o interfaces: implementamos um método independente de uma hierarquia de classes. Isto permite reduzir o nível de acoplamento entre classes, uma vez que não dependemos de uma herança para que o método seja implementado. Quando usar métodos abstratos e interfaces ? Depende do nível exigido de acoplamento entre classes e do que você quer reutilizar nas implementações. Se o seu objetivo é reduzir acoplamento, interfaces são uma boa opção. Por outro lado, se o seu objetivo é maximizar reuso, métodos abstratos podem ser a melhor opção. INTRODUÇÃO AO JAVA COLLECTIONS A classe ArrayList, utilizada em implementações na nossa disciplina, faz parte de um framework chamado Java Collections, cuja finalidade é disponibilizar classes genéricas para estruturas de dados. Grande parte das classes do framework Java Collections é formada por classes genéricas e, suas classes e interfaces principais, são mostradas na figura seguinte. Podemos definir coleção como a representação de um grupo de objetos. No entanto, as coleções são implementações, como temos visto, que geralmente encapsulam arrays, oferecendo: o Buscao Inserção o Redimensionamento dinâmico o remoção de elementos o ordenação 7 Uma das vantagens de se utilizar coleções ou collections é o fato de não ser necessário implementar métodos de ordenação, busca, redimensionamento e etc As principais interfaces do Java Collections são: Listas (List), Conjuntos (Set) e Mapeamento (Map) https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html A API de Collections traz a interface java.util.List, que significa o que uma classe deve ser capaz de fazer para ser uma lista. A interface List define uma coleção ordenada, também conhecida como sequência, em que podemos controlar a posição em que os elementos são inseridos. Desse modo, é possível acessá-los através de um índice inteiro (posição na lista). Normalmente as classes que implementam esta interface permitem elementos duplicados e elementos null. 8 A INTERFACE COMPARABLE A interface List é utilizada para armazenar objetos de mesma classe. Esses objetos são armazenados de acordo com a ordem de inclusão. Podemos armazenar valores nulos e objetos duplicados. Apesar da estrutura manter os dados de acordo com a ordem de inclusão, é possível ordenar os objetos armazenados em um List usando uma "ordem natural". Contudo, é necessário definir a "ordem natural“. Para isso, a classe a ser armazenada na List precisa implementar a interface Comparable juntamente com seu método compareTo(). Vamos utilizar o método estático sort() da classe utilitária Collections para fazer a ordenação dos objetos armazenados na List. Para ordenar uma lista de objetos, devemos executar o método estático Collections.sort(List). A interface Comparable (java.lang.Comparable) é implementada por classes que são ordenáveis, ou seja, que podem ser automaticamente ordenadas por coleções ou outras classes. A interface Comparable obriga com que a classe implemente o método compareTo(). Esse método contém a regra (ordem natural) de ordenação, que define a precedência dos objetos das instâncias da classe que a implementa. A assinatura do método: int compareTo(Object object) Exemplo: o A classe String é um exemplo de classe que implementa a interface Comparable. Sua implementação do método compareTo() faz a análise caracter a caracter para definição da ordenação de Strings. o Pelo conceito de "ordem natural" da String, a instância "Bruno de Almeida" estaria localizada antes da instância "Cesar Gomes", pois a letra 'B' antecede a letra 'C'. Utilizando classes criadas durante a abstração de um objeto do mundo real, nem sempre temos um parâmetro adequado para comparar duas instâncias de uma mesma classe. Por exemplo: o Dada uma classe Funcionário, com os atributos nome, RG e Registro Funcional, qual dos parâmetros deve ser utilizado para definir a "ordem natural" do objeto? 9 O método compareTo() utilizado para comparar a instância atual com qualquer outra instância da mesma classe retornar os seguintes valores: o -1 (ou um número negativo qualquer): deve retornar esse valor se o objeto estiver "antes" daquele passado como parâmetro o 0: deve retornar esse valor se os objetos forem iguais o 1 (ou um número positivo qualquer): deve retornar esse valor se o objeto estiver "depois" daquele passado como parâmetro EXERCÍCIO TUTORIADO Considere uma classe Aluno possui dois atributos: nome e tia. A ordem natural dos objetos desta classe foi definida da seguinte forma: o Primeiramente os objetos serão ordenados pelo atributo "nome" seguindo a ordem alfabética o Em caso de empate (nomes iguais) será utilizado o "tia" como segundo critério para desempate Implemente a classe Aluno e uma classe Principal para testar a classe Aluno. 10 ATIVIDADES DE LABORATÓRIO 1. A nossa classe ATM, implementada em aula, estava vinculada somente a um banco. Nesta primeira parte da atividade, vamos permitir que um mesmo caixa eletrônico esteja vinculado a diversos bancos. Para isto: a. Refatore a implementação da classe Bank para ele tenha um identificador numérico (int) e um nome. Por exemplo: 1 – Banco do Brasil b. Refatore a interface BankAccountOperation para que as operações bancárias recebam a identificação numérica do banco c. Refatore a implementação de Bank para se ajustar a nova interface BankAccountOperation d. Refatore a implementação de ATM para que armazene uma coleção de bancos possíveis para realizar as operações e implemente a nova interface BankAccountOperation. A inicialização da coleção de bancos possíveis deve ser realizada através da leitura de um arquivo com o seguinte formato: Número de Bancos Identificador numérico Banco 1 # Nome do Banco 1 Identificador numérico Banco 2 # Nome do Banco 2 ... Identificador numérico Banco N # Nome do Banco N 1. Ordene esta nova coleção em ordem crescente de saldo. Porém, você deve usar o método sort() da Collections. Para isso sua classe Bank deve implementar a interface Comparable. 2. Finalmente, implemente uma classe User que disponibilize métodos sobrecarregados estáticos void doOperation(BankAccountOperation bao, byte type,... ), que recebam uma implementação da interface BankAccountOperation, um tipo de operação (0 – saldo, 1 – depósito e 2 – saque) e demais informações necessárias à operação (número da conta, identificador do banco, valor, etc), realizando-a em seguida. Caso ocorra uma exceção, a classe User deve tratar a exceção, informando que a operação não foi realizada. Junto com as implementações acima, entregue as classes de teste que guiaram as suas implementações via TDD. 11 EXERCÍCIOS EXTRA-CLASSE 1. Implemente uma interface chamada OperationLog e que possua um método com a assinatura abaixo: public void log(String fileName, Date d, int bankID, String bankName, String opType, int accountNumber, double value); Esta operação deverá armazenar, no final do arquivo de nome fileName, cada operação realizada numa linha, conforme abaixo: DatadaOperação # IdentificadordoBanco # NomedoBanco # NomedaOperação # Númeroda conta # Valordaoperação No caso de consulta de saldo, o valor da operação deverá ser 0. 2. Refatore as classes Bank e ATM para que implementem a interface acima, além da interface BankAccountOperation.
Compartilhar