Agrupamento de Classes Packages – agrupar classes de acordo coma sua funcionalidade – Ex: package java.io package java.util Qualquer classe ou membro de uma classe pode ser referenciada de forma absoluta usando como prefixo o nome do package, seguido do identificador da entidade a que se pretende aceder java.lang.String.size() java.io.System.out.println(“aula”) Pode-se usar a cláusula de importação – torna elementos importados disponíveis na definição da classe que os importa (desnecessário usar prefixos) import java.util.Vector; import java.lang.String; import java.util.*; importação global 77 Modificadores de acesso Modificadores de acesso public protected private Definido por omissão (=package) 78 1 Modificadores de acesso Classes Uma classe é sempre acessível a todas as outras classes que pertençam ao mesmo package Membros e construtores private int numero; - acessível só na classe protected int getMinimo() – acessível do mesmo package e das subclasses public int getNumero() – acessível em todas as classes e packages Int getUserID() – acesso package •Acesso de classes sobrepõe acesso métodos/construtores •Para um membro (ou construtor) ter acesso public, ambos o membro (ou o construtor) e a classe têm que ser declarados public 79 Exemplo: acesso para construtores e membros declarados na classe C package A Class C package B Subclasse da Class C private Package Protected public 80 2 Variáveis de instância e de classe VARIÁVEIS DE INSTÂNCIA ≈ VARIÁVEIS LOCAIS VARIÁVEIS DE CLASSE COMUNS A TODAS AS INSTÂNCIAS DEFINIDAS COM static class MembroFamilia { static String apelido = "Oliveira"; String nome; int idade; UM VALOR ... PARA CADA } INSTÂNCIA UM VALOR PARA TODAS AS INSTÂNCIAS 81 Classes abstractas Exemplo: Simulação raposas e coelhos Fonte: Objects first with Java: a practical introduction using BlueJ, David Barnes, Michael Kolling, Prentice Hall/Pearson 82 3 Exemplo: Simulação raposas e coelhos Crie um objecto Simulator, usando o construtor sem parâmetros Simule o “ambiente” raposas-coelhos O número de raposas varia em cada simulação? Que processos naturais acha que está a modelar quando o número de raposas aumenta e diminui? 83 public class Rabbit { // Characteristics shared by all rabbits (static fields). // The age at which a rabbit can start to breed. private static final int BREEDING_AGE = 5; // The age to which a rabbit can live. private static final int MAX_AGE = 50; // The likelihood of a rabbit breeding. private static final double BREEDING_PROBABILITY = 0.15; // The maximum number of births. private static final int MAX_LITTER_SIZE = 5; // A shared random number generator to control breeding. private static final Random rand = new Random(); // Individual characteristics (instance fields). // The rabbit's age. private int age; // Whether the rabbit is alive or not. private boolean alive; // The rabbit's position private Location location; … 84 4 public void simulateOneStep() { // add new born animals to the list of animals animals.addAll(newAnimals); step++; newAnimals.clear(); // Swap the field and updatedField at the end of the step. Field temp = field; field = updatedField; updatedField = temp; updatedField.clear(); // let all animals act for(Iterator iter = animals.iterator(); iter.hasNext(); ) { Object animal = iter.next(); if(animal instanceof Rabbit) { Rabbit rabbit = (Rabbit)animal; if(rabbit.isAlive()) { rabbit.run(updatedField, newAnimals); } else { iter.remove(); // remove dead rabbits from collection } } else if(animal instanceof Fox) { Fox fox = (Fox)animal; if(fox.isAlive()) { fox.hunt(field, updatedField, newAnimals); } else { iter.remove(); // remove dead foxes from collection } } else { System.out.println("found unknown animal"); } } // display the new field on screen view.showStatus(step, field); } Operador instanceOf – testa se um dado objecto é, directa ou indirectamente, uma instância de uma dada classe Obj instanceOf MyClass – devolve True se o tipo dinâmico de Obj é MyClass ou qualquer subclasse de MyClass 85 Quando é necessário o operador instanceof? Usa-se instanceof em conjunto com árvores de classes, nos casos em que se manda uma mensagem apenas para uma parte da subárvore Criam-se os seguintes objectos: A objecto1 = new C(); A objecto2 = new E(); Pode-se, correctamente, mandar a mensagem metodo1() para ambos os objectos: objecto1.metodo1(); objecto2.metodo2(); Só se pode mandar a mensagem metodo2() para subclasses da classe B metodo1() If(objecto1 instanceof B) { A abstracto em A B umObjecto = (B) objecto1; umObjecto.metodo2(); } metodo2() B C D abstracto em B E F metodo1() implementado aqui metodo2() implementado aqui 86 5 Melhorar a simulação - Refactoring Refactoring – processo de reestruturar um desenho existente (classes e métodos) para adaptá-los a alterações de requisitos, mantendo um bom desenho, facilitando (prevendo) alterações futuras Identificar as semelhanças entre as classes Fox e Rabbit. Fazer listas separadas de variáveis, métodos e construtores e distinguir as variáveis de classe e de instância. 87 Herança Animal Fox Rabbit Herança – evita duplicação de código em Fox e em Rabbit – facilita a adição de novos animais, no futuro – e a classe Simulator? 88 6 Melhorar a classe Simulator Versão 1 Utiliza verificações de tipo explícitas (usando operador instanceOf) e casts para determinados tipos de animal para implementar um passo da simulação Como melhorar? for(Iterator iter = animals.iterator(); iter.hasNext(); ) { Animal animal = (Animal)iter.next(); if(animal.isAlive()) { animal.act(field, updatedField, newAnimals); } else { iter.remove(); // remove dead animals from collection } 89 A variável usada para cada elemento da colecção (animal) é do tipo Animal (todos os objectos na colecção são fox ou rabbit, isto é, são subtipos de Animal Assume-se que os métodos de acção (run para Rabbit e hunt para Fox) foram renomeados act (chamada polimorfa aos métodos em cada classe) Como o tipo dinâmico das variáveis determina qual o método a ser executado, o método de acção para as raposas será executado para raposas e o dos coelhos para coelhos Uma vez que a verificação de tipos é feita usando os tipos estáticos, o código só compilará se a classe Animal tiver um método act com a devida assinatura: animal. act (field, updatedField, newAnimals); Cada animal tem uma dada “acção”, mas não podemos definir uma acção para animal em geral. E então? 90 7 Classes abstractas Como definir o método act de Animal? Nunca vai existir uma instância da classe Animal – Todos os animais são uma instância de alguma subclasse Classes abstractas – classes que não são instanciadas mas que servem apenas de superclasses Para declarar uma classe como abstracta utilizar palavra abstract no cabeçalho da classe: – public abstract class NomeClasse Método abstracto – a definição de um método abstracto consiste na sua assinatura sem o corpo do método e com o prefixo abstract, terminando com ; abstract public void act (Field currentField, Field updatedField, List newAnimals); 91 Porque não mudar o método canBreed para Animal? – Utilização de variáveis de classe dificulta – BREEDING_AGE – Seria necessário usar um método para aceder a Breeding_age Public boolean canBreed() // na class Animal {return age >= getBreedingAge();} » Um método abstracto em Animal » E métodos concretos em Fox e Rabbit – Mover o método incrementAge de Fox e Rabbit para Animal – definir um método abstarcto getMaxAge em Animal e versões concretas em Fox e Rabbit 92 8 Herança Múltipla Simulação Raposas/Coelhos – novas potencialidades – Adicionar outros animais – Adicionar outros participantes que podem não ser animais » Predadores humanos que podem caçar e ser caçados » Incluir plantas ou mesmo o tempo 93 Actor <<Abstract>> Animal A única coisa que todos os actores têm em comum é que executam alguma acção Superclasse de todos os participantes, sejam eles quais forem <<Abstract>> Simulador Raposa Caçador Coelho public abstract class Actor { abstract public void act (Field currentField, Field updatedField, List newAnimals); } 94 9 Expandir Simulação Coelhos/Raposas 1. Introduzir a classe Actor 2. Reescrever o método SimulateOneStep da classe Simulator para usar Actor em vez de Animal • Simulação gere objectos Actor – maior abstracção • Criar diferentes cenários para a simulação • Meio aquático com tubarões, peixes, … • Alimentação – plankton – visualizar? É muito e muito pequeno • Modelar o tempo, apesar de actor também não é preciso visualizá-lo Separar visualização de actuação 95 Separar visualização de actuação no problema da simulação Alterar forma como é feita a visualização na simulação – Em vez de percorrer todo o campo de cada vez e desenhar os actores em cada posição, pode-se percorrer uma colecção diferente de actores “visualizáveis”: // todos os animais agem for (Iterator iter = actors.iterator(); iter.hasNext();) { Actor actor = (Actor) iter.next(); actor.act(…); } // visualiza (desenha) todos os visualizáveis for (Iterator iter = drawables.iterator(); iter.hasNext();) { Drawable item = (Drawable) iter.next(); item.draw(…); } 96 10 Implementa o método abstracto Draw Herança Múltipla Classe herda de mais do que uma superclasse <<Abstract>> Drawable <<Abstract>> Actor <<Abstract>> Animal Raposa Coelho Caçador Formiga Formigas agem mas não são visíveis no ecrã 97 Implementação de Herança Múltipla Linguagens OO variam no tratamento da herança múltipla – Algumas permitem outras não Java não permite – Mas fornece um mecanismo que possibilita uma forma limitada de herança múltipla INTERFACES 98 11 Java Interfaces Interface – especificação de um tipo que não define qualquer implementação para os métodos Semelhantes a classes, mas a definição dos métodos não inclui o “corpo” do método – Semelhantes a classes abstractas, nas quais todos os métodos são abstractos 99 Interface Actor /** * Interface para ser estendida por qualquer classe que pretenda * Participar na simulação */ Todos os métodos são abstractos – desnecessária palavra abstract na declaração do método public interface Actor { // executa o comportamento do actor void act (Field currentField, Location location, Field updatedField); } Todos os métodos são publicos – desnecessário public • • Interfaces não contêm construtores Só são permitidas constantes numa interface 100 12 Java Interfaces • Uma classe herda de uma interface da mesma maneira que herda de outra classe • Java usa outra palavra para herança de interfaces – implements • Uma classe implementa uma interface se inclui a clausula impelments no seu cabeçalho de classe: public class Fox extends Animal implements Drawable {….} Colocar primeiro extends nestes casos Das classes Drawable, Actor, Animal, Caçador, Coelho e Raposa, quais as que podem ser reescritas como interfaces? – Redefinir Actor 101 Herança múltipla de interfaces Uma classe pode implementar qualquer número de interfaces Se Actor e Drawable forem interfaces em vez de classes abstractas, a classe Caçador implementa as duas: public class Caçador implements Actor, Drawable {….} Classe Caçador herda as definições dos métodos de todas as interfaces (act e draw) – Tem que fornecer as definições desses métodos, ou será declarada abstracta 102 13 Interfaces como tipos Quando uma classe implementa uma interface, não herda nenhuma implementação, visto que uma interface não contém “corpos” de métodos – O que se ganha implementando interfaces? Benefícios da herança? – Reutilizar de código e evitar duplicação de código – subclasse herda da superclasse – Permite que casos diferentes de objectos (instâncias das subclasses) sejam tratadas uniformemente (como instâncias do supertipo) – subclasse torna-se um subtipo da superclasse - polimorfismo Interfaces não têm a primeira vantagem Mas têm a segunda – uma interface define um tipo tal como uma classe o faz: as variáveis podem ser definidas como sendo de tipos interface, mesmo que não existam objectos desse tipo (só subtipo) – Sendo Actor uma interface, pode-se ainda declarar uma variável do tipo Actor na classe Simulator 103 Interfaces como especificações Interfaces separam a definição da funcionalidade (a interface da classe no sentido mais lato) da sua implementação Exemplo: Hierarquia da Java collection Especifica a funcionalidade da List sem detalhes de implementação <<interface>> List implements ArrayList implements LinkedList Duas implementações diferentes da mesma interface, que diferem na eficiência de algumas funções private List myList = new ArrayList (); (ou LinkedList) 104 14 Classes abstractas – quando usar • Para modelar um objecto generalizável, não apenas para capturar funcionalidades comuns • A classe abstrai um conjunto de classes que partilham características, apesar de poderem ter implementações diferentes • A especificação publica da classe abstracta reflecte a parte comum das subclasses • A decisão de usar generalização deve ser feita com cuidado. Uma subclasse concreta depende fortemente da sua superclasse abstracta – fortemente acopladas • A especificação de uma classe abstracta deve ser estável • Uma classe abstracta deve incluir detalhes comuns de implementação das suas subclasses; se não houver implementações comuns, deve-se então usar uma interface 105 Utilização de abstracção para organizar listas Listas com qualquer tipo de elementos: Alunos, Quartos, Funcionalidade básica fornecida por uma lista é independente do tipo de elementos: adicionar, remover, aceder a itens – Explorar funcionalidade comum Mesmo algoritmo para ordenar lista de alunos, lista de salários – Implementar algoritmo de ordenação e usá-lo para qualquer tipo de lista – Métodos ordenação - aceitar argumentos List » Necessitam de uma ordenação, definida nos componentes da lista – lessThen – Como se são Objects? – Também pretendemos ordenar nomes, números, … Lista e ordenação têm que ser especificados 106 15 Criação de Classes Algumas directivas Variáveis de instância devem ser private (encapsulamento) Inicializar dados explicitamente através de construtores Não usar demasiados tipos básicos numa classe Usar uma forma consistente na definição de classes Constantes de classe Variáveis de classe Métodos de classe Construtores Variáveis de instância Métodos de instância Usar identificadores de classes, variáveis e métodos com significado Reutilizar classes já existentes no JDK 107 16