77
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
Modificadores de acesso
Modificadores de acesso
public
protected
private
79
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
80
Exemplo: acesso para construtores e membros declarados na classe C
package A package B Class C private Package Protected public Subclasse da Class C
81
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 TODAS AS INSTÂNCIAS UM VALOR PARA CADA INSTÂNCIA
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
83
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?
84
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;
85
public void simulateOneStep()
{ step++; newAnimals.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"); }
}
// add new born animals to the list of animals animals.addAll(newAnimals);
// Swap the field and updatedField at the end of the step.
Field temp = field; field = updatedField; updatedField = temp; updatedField.clear();
// 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
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 If(objecto1 instanceof B) { B umObjecto = (B) objecto1; umObjecto.metodo2(); } A B C D E F metodo1() implementado aqui metodo2() implementado aqui metodo2() abstracto em B metodo1() abstracto em A
87
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.
88
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?
89
Melhorar a classe Simulator
Versão 1
Utiliza verificações de tipo explícitas (usando operador instanceOf) e
castspara 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 }
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?
91
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);
92
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
93
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
Animal
Raposa Coelho
Caçador Actor
Simulador Superclasse de todos os
participantes, sejam eles quais forem
<<Abstract>>
<<Abstract>>
public abstract class Actor {
abstract public void act (Field currentField, Field updatedField, List newAnimals); }
A única coisa que todos os actores têm em comum é que executam alguma acção
95
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
96
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(…); }
97 Animal Raposa Coelho Caçador Actor Drawable <<Abstract>> <<Abstract>> Formiga
Herança Múltipla
<<Abstract>> Implementa o método abstracto Draw Formigas agem mas não são visíveis no ecrã Classe herda de mais do que uma superclasseImplementaçã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
99
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
100
Interface Actor
/**
* Interface para ser estendida por qualquer classe que pretenda * Participar na simulação
*/
public interface Actor
{ // executa o comportamento do actor
void act (Field currentField, Location location, Field updatedField); }
• Interfaces não contêm construtores
• Só são permitidas constantes numa interface
Todos os métodos são abstractos – desnecessária palavra abstract na declaração do método
Todos os métodos são publicos – desnecessário public
101
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 {….}
Das classes Drawable, Actor, Animal, Caçador, Coelho e Raposa, quais
as que podem ser reescritas como interfaces? – Redefinir Actor
Colocar primeiro extends nestes casos
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
103
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
104
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
List <<interface>> ArrayList LinkedList implements implements Especifica a funcionalidade da List sem detalhes de implementação
Duas implementações diferentes da mesma interface, que diferem na eficiência de algumas funções
105
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
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
107
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