Programação Orientada a Objetos em Java Leandro Tonietto Programaçao I Cursos de Informática da Unisinos [email protected] http://www.inf.unisinos.br/~ltonietto/inf/pg1/ProgramacaoOO_Java.pdf 08-11 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto Sumário Resumo/revisão sobre OO Classes simples Herança Polimorfismo Classes abstratas 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 2 Resumo sobre Orientação a objetos Perceber o mundo como objetos. Tudo no mundo são objetos: o aluno Fulano de Tal é um objeto, o aluno Beltrano também um objeto. O veículo de placas ABC-1234 é um objeto, assim como o veículo XYZ-6789. Classes são a descrição de um (ou tipo para) grupo de objetos com as mesmas propriedades e comportamentos. Elas descrevem o que os objetos contém de atributos e como é o comportamento dos mesmos Exemplos: aluno, veículo, professor, funcionário, disciplina, ... Objetos são ocorrências especificas de uma determinada classe de objetos; assim como o aluno Fulano de Tal ou o veículo ABC-1234. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 3 Resumo sobre Orientação a objetos Importante: classes descrevem quais (e de que tipo) são os atributos (campos, propriedades ou características) de tipo de objeto. Já o objeto mantém (possui e da manutenção) sobre os seus próprios dados. Todos alunos possuem a propriedade, porém cada um tem o seu. Então se diz que a classe declarou ou descreveu o atributo nome e cada objeto (ocorrência) da classe guarda um nome em memória. Todo objeto é responsável por encapsular os seus dados. Portanto, apenas ele pode interferir no estado das suas variáveis. Mais uma vez: a classe descreve como os objetos devem fazer a manutenção e cada objeto faz a manutenção (em tempo de execução) sobre os seus atributos ou dados. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 4 Resumo sobre Orientação a objetos Sistemas orientados a objetos: Objetos não existem sozinhos, eles interagem com outros objetos, formando um sistema. A interação entre objetos é feita através da invocação (chamada) de métodos de um objeto por outro. Em outras palavras, um objeto que necessite interagir com outro precisa referenciar o outro objeto e invocar os seus métodos para que estes realizem algum processamento e/ou retornem alguma informação. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 5 Resumo sobre Orientação a objetos Exemplo de classes: Disciplina Pessoa nome nome atributos atributos idade endereço peso falar() segunda-feira, 5 de março de 12 Classe definirProf(prof) métodos comer(comida) 31-Aug-11 Horário Curso Classe andar(distância) métodos Professor definirHorario(h) encerrar() iniciarAtivid() Leandro Tonietto 6 Resumo sobre Orientação a objetos Exemplo de interação entre objetos (sistema): Disciplina SistemaTurma disciplinas nome alunos Professor main() Horário Curso main(){ Disciplina d = new Disciplina(); //... int horario = lerHorario(); d.definirHorario(horario); //... } 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto definirProf(prof) definirHorario(h) encerrar() iniciarAtivid() 7 Codificando classes em Java Para cada definição de classe (modelagem), criamos uma classe em Java. Cada classe em um arquivo separado. O arquivo-fonte Java é um arquivo texto com extensão .java Para cada classe compilada, é gerado um arquivo com extensão .class O nome do arquivo deve ter exatamente o mesmo nome da classe pública. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 8 Codificando classes em Java Sintaxe para escrever uma classe: package exemplo; // veremos mais sobre pacotes no final! import java.util.Date; // importação ou uso de bibliotecas public class NomeDaClasse [extends Base] [implements Base]{ // atributos da classe private Tipo atributo; // construtor(es) da classe. // O “padrão” não recebe parâmetros public NomeDaClasse(){...} // declaração de métodos sem retorno public void nomeDoMetodo([parâmetros]){...} 31-Aug-11 // declaração de métodos com retorno public Tipo nomeDoMetodo([parâmetros]){ ... return algumaCoisa; //obrigatório!! Leandro Tonietto } segunda-feira, 5 de março de 12 9 Codificando classes em Java Sintaxe para escrever uma classe: package exemplo; // veremos mais sobre pacotes no final! import java.util.Date; // importação ou uso de bibliotecas public class NomeDaClasse [extends Base] [implements Base]{ // atributos da classe private Tipo atributo; Conceito de interface será visto mais adiante na disciplina // construtor(es) da classe. // O “padrão” não recebe parâmetros public NomeDaClasse(){...} // declaração de métodos sem retorno public void nomeDoMetodo([parâmetros]){...} 31-Aug-11 // declaração de métodos com retorno public Tipo nomeDoMetodo([parâmetros]){ ... return algumaCoisa; //obrigatório!! Leandro Tonietto } segunda-feira, 5 de março de 12 9 Codificando classes em Java Pessoa Exemplo: # nome # dataNascimento # cpf +Pessoa(nome) +setNome(nome) +setDataNascimento(data) +setCPF(cpf) +getNome() +getDataNascimento() +getCPF() Aluno - matrícula +Aluno(nome, matrícula) +setMatricula(matricula) +getMatricula() 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 10 Codificando classes em Java Pessoa # nome # dataNascimento # cpf Exemplo: Quantos arquivos .java codificaremos? Segundo o padrão, qual deve ser o nome de cada arquivo? Por arquivo devemos começar? +Pessoa(nome) +setNome(nome) +setDataNascimento(data) +setCPF(cpf) +getNome() +getDataNascimento() +getCPF() Aluno - matrícula +Aluno(nome, matrícula) +setMatricula(matricula) +getMatricula() 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 10 Codificando classes em Java Pessoa # nome # dataNascimento # cpf Exemplo: Quantos arquivos .java codificaremos? Segundo o padrão, qual deve ser o nome de cada arquivo? Por arquivo devemos começar? Aluno - matrícula +Aluno(nome, matrícula) +setMatricula(matricula) +getMatricula() 31-Aug-11 segunda-feira, 5 de março de 12 +Pessoa(nome) +setNome(nome) +setDataNascimento(data) +setCPF(cpf) +getNome() +getDataNascimento() +getCPF() Respostas: Dois, um para cada classe Pessoa.java e Aluno.java Pela classe Pessoa, pois Aluno depende de Pessoa para existir! Leandro Tonietto 10 Codificando classes em Java 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 11 Codificando classes em Java Sintaxe para escrever a classe Pessoa (arquivo Pessoa.java): package exemplo; // pacote da classe import java.util.Date; // importação de bibliotecas public class Pessoa { // atributos da classe protected String nome; // classe Date implementa objeto de data protected Date dataNascimento; protected long cpf; // construtor(es) da classe public Pessoa(String n){ nome = n; cpf = 0; dataNascimento = null; } 31-Aug-11 public public public public public public void setNome(String n){ nome = n;} String getNome(){ return nome; } void setDataNascimento(Date d){ dataNascimento = d; } Date getDataNascimento(){ return dataNascimeneto; } void setCPF(long c){ cpf = c; } 11 Leandro Tonietto long getCPF() { return cpf; } segunda-feira, 5 de março de 12 Codificando classes em Java Sintaxe para escrever a classe Pessoa (arquivo Pessoa.java): package exemplo; // pacote da classe import java.util.Date; // importação de bibliotecas public class Pessoa { // atributos da classe protected String nome; // classe Date implementa objeto de data protected Date dataNascimento; protected long cpf; // construtor(es) da classe public Pessoa(String n){ nome = n; cpf = 0; dataNascimento = null; } 31-Aug-11 public public public public public public Pessoa # nome # dataNascimento # cpf +Pessoa(nome) +setNome(nome) +setDataNascimento(data) +setCPF(cpf) +getNome() +getDataNascimento() +getCPF() void setNome(String n){ nome = n;} String getNome(){ return nome; } void setDataNascimento(Date d){ dataNascimento = d; } Date getDataNascimento(){ return dataNascimeneto; } void setCPF(long c){ cpf = c; } 11 Leandro Tonietto long getCPF() { return cpf; } segunda-feira, 5 de março de 12 Codificando classes em Java Sintaxe para escrever a classe Pessoa (arquivo Pessoa.java): package exemplo; // pacote da classe import java.util.Date; // importação de bibliotecas public class Pessoa { // atributos da classe protected String nome; // classe Date implementa objeto de data protected Date dataNascimento; protected long cpf; // construtor(es) da classe public Pessoa(String n){ nome = n; cpf = 0; dataNascimento = null; } 31-Aug-11 public public public public public public O que significa declarar um atributo com modificador protected? Pessoa # nome # dataNascimento # cpf +Pessoa(nome) +setNome(nome) +setDataNascimento(data) +setCPF(cpf) +getNome() +getDataNascimento() +getCPF() void setNome(String n){ nome = n;} String getNome(){ return nome; } void setDataNascimento(Date d){ dataNascimento = d; } Date getDataNascimento(){ return dataNascimeneto; } void setCPF(long c){ cpf = c; } 11 Leandro Tonietto long getCPF() { return cpf; } segunda-feira, 5 de março de 12 Codificando classes em Java Considerações sobre a classe Pessoa Atributos protected são privados ao meio externo, com exceção das classes-derivadas (ou subclasses) Normalmente, se um atributo é privado ou protegido, deve-se ter alguma forma defini-lo (set) ou obtê-lo (get) de visibilidade pública. Métodos GET e SET são uma conveção ou padrão para programação. A maioria das bibliotecas e programas utilizam estes prefixos nos nomes dos métodos para, respectivamente, obter e definir o valor de um atributo. Construtor tem a mesma grafia que a classe. Objeto do tipo Date permite encapsulamento de um dado como uma data. Datas, apesar de serem tipos de dados comuns, não são um tipo de dado primitivo; há um classe que encapsula seu comportamento e atributos em java: java.util.Date. A classe Pessoa contém apenas os dados e atributos relativos a uma pessoa, apenas isso. Não é um sistema orientado a objetos, apenas um componente de um sistema. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 12 Codificando classes em Java Herança: Na programação OO, quando falamos em herança, dizemos que uma classe herda de outra e estende as suas funcionalidades. Em Java, para indicar que uma classe estende outra, usamos o “comando”: extends. Quando uma classe B estende uma classe A, significa que B possui os mesmos comportamentos e atributos de A e ainda define os próprios. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 13 Codificando classes em Java Herança em Java (arquivo Aluno.java): package exemplo; // pacote da classe public class Aluno extends Pessoa { // atributos da classe private int matricula; // construtor(es) da classe. // Se o da classe Pessoa possui algum atributo, // o da classe Aluno deve contemplá-lo. public Aluno (String n, int m){ // invoca algum construtor da classe-base super(n); matricula = m; } 31-Aug-11 public void setMatricula(int m){ matricula = m;} public int getMatricula(){ return matricula; } public void imprimir(){ super.imprimir(); System.out.println(“Matricula: ”+matricula); } Leandro Tonietto segunda-feira, 5 de março de 12 14 Codificando classes em Java Herança em Java (arquivo Aluno.java): package exemplo; // pacote da classe public class Aluno extends Pessoa { // atributos da classe private int matricula; // construtor(es) da classe. // Se o da classe Pessoa possui algum atributo, // o da classe Aluno deve contemplá-lo. public Aluno (String n, int m){ // invoca algum construtor da classe-base super(n); matricula = m; } 31-Aug-11 public void setMatricula(int m){ matricula = m;} public int getMatricula(){ return matricula; } public void imprimir(){ super.imprimir(); Aluno possui nome? E os métodos System.out.println(“Matricula: ”+matricula); getNome e setNome? Porque? } Leandro Tonietto segunda-feira, 5 de março de 12 14 Codificando classes em Java Herança em Java (arquivo Aluno.java): package exemplo; // pacote da classe public class Aluno extends Pessoa { // atributos da classe private int matricula; Aluno - matrícula +Aluno(nome, matrícula) +setMatricula(matricula) +getMatricula() // construtor(es) da classe. // Se o da classe Pessoa possui algum atributo, // o da classe Aluno deve contemplá-lo. public Aluno (String n, int m){ // invoca algum construtor da classe-base super(n); matricula = m; } 31-Aug-11 public void setMatricula(int m){ matricula = m;} public int getMatricula(){ return matricula; } public void imprimir(){ super.imprimir(); Aluno possui nome? E os métodos System.out.println(“Matricula: ”+matricula); getNome e setNome? Porque? } Leandro Tonietto segunda-feira, 5 de março de 12 14 Codificando classes em Java Classe Aluno: Deve declarar e implementar os seus atributos e métodos. Possui todos os atributos e métodos de Pessoa. Aluno é uma Pessoa. Para indicar herança, usar comando extends A classe e os objetos Aluno não tem acesso direto aos atributos private de Pessoa. Ela tem acesso apenas aos públicos e protegidos. Objeto super se refere a classe-base. Comando super() se refere ao construtor da classe-base. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 15 Codificando classes em Java Criando objetos e fazendo o sistema funcionar: Para se utilizar um objeto da classe é necessário criar uma instância (alocar memória). Utilizando o operador new: Aluno a; // declaração do objeto a = new Aluno(“Fulano”, 1233); // instanciação Classe principal: É aquela que possui o método: public static void main(String args[]) Todos os objetos e métodos utilizados neste arquivo / classe devem ser estáticos, pois o método main é estático. Objetos podem ser criados dentro do main. É a classe por onde a JVM começa a execução de um sistema Java. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 16 Codificando classes em Java Instanciação de objetos //em algum lugar do main... // apenas declaração Pessoa p; // apenas declaração Aluno a; // instanciação/alocação p = new Pessoa(“Beltrano”); // instanciação/alocação a = new Aluno(“Fulano”, 123); Repare que a instanciação de Pessoa aloca uma área de memória de tamanho X. Já a alocação de Aluno, aloca uma quantidade X + Y; onde X é a área ocupada por um objeto Pessoa e Y é a área necessária para armazenar informação específicas de Aluno. Lembre-se: O Aluno É uma Pessoa, portanto carrega todas as propriedades de Pessoa também. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto Memória Pessoa p Aluno a new Pessoa: nome=Beltrano new Pessoa alocada pelo new Aluno: nome = Fulano new Aluno: matricula=123 17 Codificando classes em Java Classe principal: package exemplo; public class Programa { public static void main(String args[]){ // objeto apenas declarado Aluno a; // objeto sendo instanciado. // neste momento o construtor é invocado a = new Aluno(“Fulano”, 1233); System.out.println(“Nome: “+a.getNome()); } } O que faz este programa? 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 18 Codificando classes em Java Exercício 1 – Modelar e programar: Fazer uma calculadora que executa as operações aritméticas básicas: adição, subtração, multiplicação, divisão e módulo. As operações devem ser realizadas sobre número do tipo float. O programa deve criar uma calculadora, mostrar um menu das opções de operação, ler uma opção, solicitar o cálculo para objeto calculadora e imprimir o resultado. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 19 Codificando classes em Java Exercício 2 – Modelar e programar Agenda de contatos. O sistema de agenda deve manter uma lista de contatos. Um contato padrão tem: nome, e-mail, telefone, endereço e data do aniversário. Porém o contato pode ser enquadrado como de algum tipo específico: geral, cliente ou fornecedor. Para fornecedor, é interessante manter-se um índice de qualidade, pois pode ser necessário ter de escolher 1 entre vários fornecedores de um mesmo produto. Já para o cliente, deve-se atribuir uma data da última compra e uma classificação de fidelidade (ou valores possíveis são: fiel, freqüente, pouco freqüente e apenas uma vez). Por fim, da categoria geral, não é necessário guardar mais nenhum dado além dos do contato. O programa da agenda deve manter um menu de opções do programa: incluir contato (acrescenta no array), excluir contato (retirar do array), listar contatos, consulta dados de um contato e sair. OBS: repare que a remoção de um contato do início ou “meio” array implica em mover os posteriores para a frente. A inclusão de contatos ocorrente sempre no final do array. Dica: manter um apontador para o último índice utilizado. Por exemplo, supondo que o array tem capacidade para 20 elementos e apenas cinco contatos foram incluídos, então esta variável deveria estar com valor 4 (array começa com zero...) 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 20 Codificando classes em Java Polimorfismo Polimorfismo é a capacidade de assumir formas diferentes. Em termos de orientação a objetos, significa que uma mesma operação pode ser definida por diversas classes, cada uma implementando a operação de uma maneira própria. Polimorfismo permite que o programador acesse um método de um objeto sem saber exatamente de qual classe específica o método esta sendo acessado 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 21 Codificando classes em Java Sobreposição (overwriting) Métodos com a mesma assinatura que são sobrescritos (substituídos). Por exemplo, um método declarado na superclasse, se redefinido na subclasse, é substituído por este em tempo de execução. Sobrecarga (overloading) Métodos com mesmo nome em uma classe podem executar operações de maneiras distintas. Isso é permitido pela diferenciação na passagem de parâmetros. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 22 Codificando classes em Java Polimorfismo (exemplo de sobrescrita): A classe Pessoa possui método imprimir() que imprime o nome e o código da pessoa. A classe Aluno estende a classe Pessoa e também possui o método imprimir(). Um objeto é declarado como da classe Pessoa, porém é instanciado como Aluno. Pessoa p = new Aluno(“Fulano”, 1233); p.imprimir(); Quando o método imprimir() for invocado deste objeto, o interpretador chamará o método da classe Aluno. Se diz que o método foi sobrescrito. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 23 Codificando classes em Java Polimorfismo (exemplo de sobrecarga): Considere uma classe FuncoesMatematicas que possui os métodos menor, maior, arredondar e absoluto. Eles possuem variações das suas assinaturas para parâmetros diferentes. Por exemplo, o método menor pode retornar o menor valor entre dois dados do tipo float, double, int ou long. O mesmo vale para as outras funções/métodos. Conforme o tipo de parâmetro passado para classe no momento de invocar o método, o interpretador sabe qual é o método mais adequado a ser utilizado. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 24 Codificando classes em Java Ainda sobre sobrecarga, considere o código: Retangulo r = new Retangulo(); r.setLargura(100, 200); r.setLargura(0.5f, 0.7f); Os métodos setLargura definem a largura do retângulo. Os dois tem o mesmo nome, mas cada um solicita um tipo de parâmetro, respectivamente, int e float. O compilador sabe qual método invocar pelo tipo de dado passado por parâmetro: isto é sobrecarga. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 25 Codificando classes em Java A classe Object Pode-se considerar a classe “mãe-detodas”. É a classe base para qualquer outra em Java. Não necessita da instrução extends; é automática. Sendo assim, todo objeto instanciado como de uma classe X é um subtipo de Object. Portanto, todos os objetos são instâncias de Object. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 26 Codificando classes em Java A classe Object. Métodos herdados: public String toString(){...} Retorna uma representação de String do objeto Por padrão, retorna: getClass().getName()+'@'+Integer.toHexString(hashCode()) Pode ser sobrescrito para imprimir alguma informação do objeto: System.out.println(funcionario); Pode imprimir os dados do funcionário: nome + “ salário: ”+salario; public boolean equals(Object outroObjeto){...} Testa se o objeto é igual a outroObjeto Deve ser sobrescrito para indicar quando um objeto é igual a outro do mesmo tipo, por exemplo, dois funcionários são iguais quando tem o mesmo nome apenas. public Object clone() {...} Retorna uma instância nova de um objeto com os dados do objeto; áreas de memória diferente, mas com os mesmos dados. É diferente de um = outro. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 27 Codificando classes em Java Exemplo/Exercício: Classe Funcionário com os atributos matricula, nome e salário. Tem também a implementação (sobrescrita) dos métodos equals(), toString() e clone(). Classe Departamento com os atributos nome e código. Sem a sobrescrita dos métodos equals(), toString() e clone(). Classe main ... 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 28 Codificando classes em Java Exemplo/Exercício: ? Funcionario f1 = new Funcionario(1, "Fulano", 1000.0); Funcionario f2 = new Funcionario(1, "Fulano", 1000.0); Departamento d1 = new Departamento(1, "Informática"); Departamento d2 = new Departamento(1, "Informática"); System.out.println("d1="+d1); System.out.println("d2="+d2); System.out.println("f1="+f1); System.out.println("f2="+f2); System.out.println("f1 == f2? "+(f1==f2)); System.out.println("d1 == d2? "+(d1==d2)); System.out.println("f1.equals(f2)? "+(f1.equals(f2))); System.out.println("d1.equals(d2)? "+(d1.equals(d2))); Funcionario f3 = (Funcionario)f1.clone(); System.out.println("f3="+f3); System.out.println("f1==f3? "+(f1==f3)); System.out.println("f1.equals(f3)? "+(f1.equals(f3))); 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 29 Codificando classes em Java Conversão de tipo (Type casting): Cast implícito (tipos primitivos apenas): Quanto ocorre um down casting por exemplo: long para double, int para double, short para float ou double, byte para float ou double double = float = long = int = short = byte; Entre objetos também ocorre: Pessoa p = professor; Isto é possível porque o Professor é uma Pessoa (herança); caso contrário, da erro; Cast explícito: Situações aonde não é possível o implícito . Conversão de objetos de classes diferentes. Por exemplo, um objeto Pessoa para Professor. Só é possível para objetos que pertençam a uma mesma hierarquia. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 30 Codificando classes em Java Continuação do exemplo: Importante: o imprimir de Aluno pode reaproveitar o imprimir da pessoa. Reescrevendo o método: public void imprimir(){ // imprime nome: imprimir da super-classe super.imprimir(); System.out.println(“Matrícula: ”+matricula); } Ao executar, considerando os dados fictícios abaixo, será: nome: Fulano de Tal matrícula: 123456 imprimir() da classe Pessoa 31-Aug-11 segunda-feira, 5 de março de 12 imprimir() da classe Aluno Leandro Tonietto 31 Codificando classes em Java Classes abstratas São classes que não possuem implementação em alguns métodos Uma classe abstrata obriga que alguma classe filha implemente os seus métodos abstratos. Recurso utilizado quando a classe base não sabe ou não pode implementar um determinada ação, mas é obrigatório que as filhas implementem. Isto é possível porque a classe base (abstrata) sinaliza os métodos que devem ser implementados. A palavra é: Polimorfismo!! 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 32 Codificando classes em Java Classes abstratas Exemplo: Uma classe FormaGeometrica é utilizada para descrever propriedades comuns a todas as classes de formas geométricas (elipses, retângulos, polígonos, triângulos, ...) A classe FormaGeometrica não sabe calcular a área de uma forma geométrica desconhecida Entretanto, cada das classes das formas geométricas específicas, sabe como é o próprio cálculo de área. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 33 Codificando classes em Java Classes abstratas Exemplo: FormaGeometrica Elipse 31-Aug-11 segunda-feira, 5 de março de 12 Retangulo Leandro Tonietto 34 Codificando classes em Java Classes abstratas Exemplo: FormaGeometrica Elipse:FormaGeometria Retangulo:FormaGeometrica int x, y int ladoA, ladoB int larg, alt abstract int calcArea() int calcArea() int calcArea() Um método abstract não é implementado, contém apenas a assinatura Classes derivadas (ou filhas) devem implementar os métodos abstratos da classe base Código ExemploAbstratas para visualizar os exemplos de classe abstrata (método abstract) 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 35 Codificando classes em Java Considere o código: FormaGeometrica fg = new Retangulo(); fg.setLargAlt(0.1f,0.2f); System.out.println(“Área: ” + fg.calcArea()); Mesmo variável sendo do tipo FormaGeometrica é invocado o calcula área da classe Retangulo. Isto porque fg é um ponteiro declarado como FormaGeometrica, mas a instância (memória alocada) é da classe Retangulo. Portanto, os métodos (sobrescritos) utilizados são os da classe Retangulo. Isto ocorre também, porque o método calcArea() é abstrato, portanto, não há implementação nele na classe-base, que é abstrata. Porém, repare que os métodos da classe Retangulo que não são sobrescritos devem ser acessados através de um cast (conversão explicita de tipos) para (Retangulo). No exemplo, setLargAlt só existe na classe Retangulo e não na FormaGeometrica. Este tipo de uso de objetos com herança, onde um objeto (ou variável) é declarado como da classe base e instanciado como da classe filha, o inverso não é possível. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 36 Codificando classes em Java Analisando a relação com a classe Elipse. Código-fonte classe FormaGeometrica: public abstract class FormaGeometrica { // posição do objeto protected float x, y; // gets e sets... // métodos abstratos public abstract float calcArea(); public abstract void desenha(); } 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 37 Codificando classes em Java Analisando a relação com a classe Elipse. Código-fonte classe Elipse: public class Elipse extends FormaGeometrica{ private float a, b; public float calcArea(){ return a * b * Math.PI; } public void desenha(){ // desenha um círculo } } 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 38 Codificando classes em Java Pacotes: São como diretórios do sistema operacional Agrupam as classes por funcionalidades: Por exemplo, as classes da biblioteca do Java (API) que manipulam banco de dados, estão sob o pacote java.sql Já as classes que manipulam entrada e saída de dados, estão no pacote java.io No código-fonte Java, a primeira instrução deve ser o pacote ao qual a classe faz parte. Deve-se usar a palavra reservada package. Exemplo: package br.unisinos.prog1.exemplos.exemplo1; O caractere “.” indica a separação dos subpacotes. Quando compilador traduz um código-fonte para código de máquina, ele cria os diretórios do pacote informado na instrução package do código-fonte. No momento de utilizar uma classe, ela deve ser referenciada pelo seu pacote ou o mesmo deve estar na instrução import: import br.unisinos.prog1.exemplos.exemplo1.Elipse; No momento de executar uma aplicação, ela deve ser referenciada pelo seu pacote: 31-Aug-11 java br.unisinos.prog1.exemplos.exemplo1.Main Leandro Tonietto segunda-feira, 5 de março de 12 39 Codificando classes em Java Modificador de visibilidade package-friendly Minimiza o encapsulamento Torna os atributos e métodos públicos apenas para as classes do mesmo pacote e determina acesso privado a todas as demais classes. Para usar este tipo de visibilidade basta não declarar nenhuma visibilidade para os atributos e métodos. Veja exemplo sobre package-friendly. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 40 Codificando classes em Java Exercício 3 - Modelar e implementar: Criar uma classe criptografia que contenha métodos para criptografar e descriptografar uma mensagem de texto. O algoritmo de criptografia é de livre escolha para o programador. É sugerido o algoritmo de substituição por deslocamento. Por exemplo, para o deslocamento 2, uma letra ‘A’ é cifrada como ‘C’, a ‘L’ como ‘N’, a ‘Z’ como ‘B’, ... Para decifrar, basta diminuir o deslocamento: um ‘C’ volta para ‘A’, ‘B’ volta para ‘Z’,... No programa principal ler uma mensagem do usuário e imprimir os resultados das operações de cifrar e decifrar uma mensagem. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 41 Codificando classes em Java Exercício 4 - Modelar e implementar Sistema de cálculo e impressão de informações de objetos geométricos. O sistema deve permitir a impressão de uma forma geométrica qualquer sem a necessidade de saber antecipadamente de qual tipo específico a forma é. Entretanto, o sistema deve suportar apenas as seguintes formas: retângulo, elipse e triângulo. Todas são formas geométricas, portanto, possuem método de cálculo de área, cálculo do perímetro e impressão dos dados. Dica: aqui deve ser usado o conceito de classe abstrata na modelagem e, em caso de construção deste sistema, use sobrecarga de operadores para impressão dos dados e área das formas geométricas. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 42 Interface Interface é um tipo de classe do Java Toda interface contém apenas atributos estáticos e assinatura de métodos públicos A interface fornece um tipo para uma classe. Se diz que uma classe implementa uma interface (equivalente a estender na herança de classes) Palavra reservada interface para criar uma interface. Palavra reservada implements para implementar uma interface numa classe. 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 43 Interface A grande utilidade do uso de interfaces é fornecer um subtipo para classes para sejam utilizadas por outras que as “desconhecem”. Outra vantagem é que uma classe pode implementar tantas interfaces quantas forem necessárias, permitindo uma herança múltipla. O que não é possível com herança simples (extends). 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 44 Interface Exemplo: Digamos que seja necessário criar uma classe que imprima qualquer classe que seja imprimível. Podemos chamar esta classe de Impressora. Para determinar quem é imprimível de Imprimivel. Sendo assim, todas as classes que são subtipo (filhas) de Imprimivel podem ser impressas. Existem duas possibilidades para se resolver este problema: 1. Fazer uma herança simples: todas as classes que estenderem uma classe Imprimivel serão objeto deste tipo, portanto podem ser utilizadas na classe Impressora. 2. Fazer uma herança através de interface: todas as classes que implementarem a interface Imprimivel, poderão serem utilizadas pela classe Impressora. (Melhor solução) 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 45 Interface Exemplo: public class Impressora { public void imprimir(Imprimivel o){ // ... Algum código o.getBytes(); } } public interface Imprimivel { public byte[] getBytes(); } 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 46 Interface Exemplo: public class Teste implements Imprimivel { public byte[] getBytes(){ return “Teste”.getBytes(); } } public class Teste2 implements Imprimivel { public byte[] getBytes(){ return “Teste 2 – outra classe”.getBytes(); } } 31-Aug-11 segunda-feira, 5 de março de 12 Leandro Tonietto 47 Interfaces • Uma interface não pode possuir nenhuma implementação; • Todos os métodos são abstratos, mesmo que o programador omita o modificador abstract; • Todos os métodos são públicos, mesmo que o modificador public seja omitido; • Todas as variáveis em uma interface são constantes, mesmo que não sejam declaradas como static final; Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 24 Interfaces interface MinhaInterface { int getSize ( ); void setSize (int param); } class MinhaClasse implements MinhaInterface { int size; Não é possível criar uma public int getSize ( ) { instância de uma interface. Para criar uma instância return size; é preciso implementar a } interface. public void setSize (int tam) { size = tam; } } Profa. Patrícia A. Jaques 25 segunda-feira, 5 de março de 12 Interfaces • Java não permite herança múltipla, por isso uma classe pode ser subclasse(extends) apenas de uma superclasse, mas implementar (implements) várias interfaces. • Podemos declarar classe abstrata Shape como interface: – retirar implementação do método Type(); – as classes que implementam Shape podem herdar propriedades de outra classes. Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 26 Inner Class • Inner class, ou nested class, é um conceito que surgiu a partir da versão JDK 1.1. Nas versões anteriores do JDK eram permitidas apenas classes top-level que pertenciam a pacotes. • A partir da versão JDK 1.1, o Java suporta classes que são membros de outras classes, ou seja, classes que são definidas dentro do escopo de uma outra classe ou são anônimas, definidas dentro de uma expressão. • Inner classes são um fenômeno do compilador e não do interpretador. Ou seja, o compilador gera o código necessário para que a inner class acesse os dados da enclosing class. Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 27 • As inner classes tem as seguintes propriedades: – O nome da inner class tem que ser diferente do nome da enclosing classe (classe o qual está dentro). – A inner classe pode usar variáveis e métodos da enclosing classe. – A inner classe pode ser definida como abstract. – A inner classe pode ser uma interface implementada por outra inner classe. – Inner classes podem ser declaradas private ou protected. Os modificadores de proteção não previnem a inner classe de acessar variáveis membros de outras classes e da enclosing class. Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 28 – Outras classes, que não a enclosing classe, não enxergam a inner classe. – Inner classes podem acessar variáveis private da enclosing class. – Se uma inner classe for declarada como static, ela se torna uma top-level classe e perde a capacidade de acessar variáveis da enclosing class. – Inner classes não podem possuir variáveis membros static. Se a inner classe precisa usar uma variável static, essa variável deve ser declarada na enclosing class. – A enclosing class pode acessar livremente os dados da inner class, mesmo os privados (private). Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 29 import java.awt.*; import java.awt.event.*; public class TestaInnerClass { private Frame f; private TextField tf; public static void main (String args []) { TestaInnerClass inner = new TestaInnerClass (); inner.inicio(); } public void inicio () { f = new Frame ("Exemplo de Inner Class"); f.add (new Label ("Clique e arraste o mouse aqui."), BorderLayout.NORTH); Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 30 tf = new TextField (30); f.add (tf, BorderLayout.SOUTH); f.addMouseMotionListener (new Tratador1()); f.addMouseListener (new Tratador2()); f.setSize(300, 200); f.setVisible(true); } // A classe Tratador1 é uma inner classe public class Tratador1 extends MouseMotionAdapter { public void mouseDragged (MouseEvent e) { String s = "Mouse Dragging: X = " + e.getX() + " Y = " + e.getY(); tf.setText (s); } } // da inner class Tratador1 Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 31 public class Tratador2 extends MouseAdapter { public void mouseEntered (MouseEvent e) { String s = "Mouse entrou"; tf.setText (s); } public void mouseExited (MouseEvent e) { String s = "Mouse saiu"; tf.setText (s); } } // da inner class Tratador2 } // da enclosing class TestaInnerClass Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 32 Classes Anônimas (Anonymous Class) f.addMouseMotionListener (new MouseMotionAdapter ( ) { public void mouseDragged (MouseEvent e) { String s = "Mouse Dragging: X = " + e.getX( ) + " Y = " + e.getY( ); tf.setText (s); } } ); • Classes Anônimas não possuem métodos construtores. Os parâmetros são repassados ao construtor da classe pai. Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 33 Garbage Collection String str = “Primeiro espaço”; System.out.println (“Usando memória original: “+str); str = “Outro espaço”; System.out.println (“Usando outro espaço de memória: “+str); Primeiro espaço str Área de memória liberada pelo Garbage Collection 10 100 Outro espaço Profa. Patrícia A. Jaques segunda-feira, 5 de março de 12 10 100 34