cap tulo 9 desenho de classes - universidade nova de lisboa
TRANSCRIPT
Capítulo 9Desenho de classes
Escolha de classes a implementar
Coesão e acoplamento
Minimização de efeitos colaterais
Consolidação de conceitos: métodos e campos estáticos, abrangência de
variáveis locais e de membros de dados, pacotes
Introdução à Programação 2007/08 A. Lopes
Escolha de classes
•Uma classe representa um conceito único num domínio específico de problemas. O seu nome deve ser um substantivo que descreve o conceito. Alguns conceitos:
•da matemática: ponto, rectângulo, círculo
•da vida real: contas bancárias, máquina de venda
•Os objectos instanciados nas classes fazem o respectivo trabalho. Por exemplo, Scanner
•Existem classes utilitárias, que não têm objectos mas apenas métodos estáticos e constantes. É o caso da classe Math
•As classes de início de execução apenas devem ter o método main
•Deve-se evitar a tradução de acções em classes: Por exemplo, TalaoVencimento e não CalculaTalaoVencimento
Introdução à Programação 2007/08 A. Lopes
Coesão
•A interface pública de uma classe demonstra coesão se todas as suas características estão relacionadas com o conceito a representar pela classe
public class CashRegister{ public void enterPayment(int dollars, int quarters, int dimes, int nickels, int pennies) public static final double NICKEL_VALUE = 0.05; ...}
Solução pouco
apropriada, pois
envolve dois conceitos:
caixa registadora e
moeda
Solução apropriada,
com duas classes
public class Coin { public Coin(double aValue, String aName){ ... } public double getValue(){ ... } ...}public class CashRegister { public void enterPayment(int coinCount, Coin coinType) { ... } ...}
Introdução à Programação 2007/08 A. Lopes
Acoplamento
•Uma classe depende de outra se usa objectos dessa classe
•CashRegister depende de Coin para determinar o valor do pagamento
•Coin não depende de CashRegister
•O acoplamento diz-se elevado quando existem muitas dependências de classe
•Devemos minimizar o acoplamento de modo a minimizar o impacto decorrente de eventuais alterações posteriores de interface
Introdução à Programação 2007/08 A. Lopes
Nível de acoplamento entre classes
•Conveniente o desenho de diagramas de classe para visualizar as relações entre classes. Por exemplo, através de UML: Unified Modeling Language, que é uma notação para análise e desenho orientado ao objecto (www.uml.org)
Introdução à Programação 2007/08 A. Lopes
Selectores, modificadores e classes imutáveis
•Selector: não altera o estado do parâmetro implícito
•Modificador: altera o objecto sob o qual foi chamado
•Classe imutável: classe que não tem métodos modificadores
•É seguro fornecer referências a objectos de classes imutáveis já que estas não modificam os objectos
double balance = account.getBalance();
account.deposit(1000);
String name = "John Q. Public";
String uppercased = name.toUpperCase();
// nome não é alterado - a classe String é imutável
Introdução à Programação 2007/08 A. Lopes
Efeitos colaterais de métodos
•Modificação de informação vista do exterior
•Sugestões
•conveniente não actualizar parâmetros explícitos
•evitar fazer modificações para além das relativas a parâmetros implícitos
•tentar dissociar input/output do trabalho efectivo das classes
public void transfer(double amount, BankAccount other){ balance = balance-amount; other.balance = other.balance+amount; // modifica parâmetro explícito}
public void printBalance() { // ... mensagem em português e dependente do System.out System.out.println("O saldo e " + balance + “!”);}
Introdução à Programação 2007/08 A. Lopes
Tentativa de modificação de um parâmetro do tipo primitivo
•Em Java, um método não consegue alterar parâmetros do tipo primitivo
void transfer(double amount, double otherBalance)
{
balance = balance - amount;
otherBalance = otherBalance + amount;
}
double savingsBalance = 1000;
harrysChecking.transfer(500, savingsBalance);
System.out.println(savingsBalance);
não funciona
Introdução à Programação 2007/08 A. Lopes
Modificação de um parâmetro sem efeito no método que chama
Introdução à Programação 2007/08 A. Lopes
Modificação de um parâmetro sem efeito no método que chama
Introdução à Programação 2007/08 A. Lopes
Chamada por valor e chamada por referência
•Chamada por valor: quando o método é chamado, os parâmetros do método são copiados para as variáveis de parâmetros
•Chamada por referência: os métodos podem modificar parâmetros
•O Java utiliza a chamada por valor
•Um método pode alterar o estado dos parâmetros de referência de objectos mas não pode substituir a referência a um objecto por outra
public class BankAccount {
public void transfer(double amount, BankAccount otherAccount) { balance = balance - amount; double newBalance = otherAccount.balance + amount; otherAccount = new BankAccount(newBalance); // não funciona }}
Introdução à Programação 2007/08 A. Lopes
Chamada por valor
harrysChecking.transfer(500, savingsAccount);
modificação do
parâmetro de
referência ao
objecto não tem
efeito prático
Introdução à Programação 2007/08 A. Lopes
Métodos estáticos
•Todo o método estático tem de estar numa classe e não é chamado para operar num objecto
•Um motivo para a existência de métodos que não operam em objectos: o encapsulamento de cálculos que envolvam apenas números, os quais, não sendo objectos, não possibilitariam a chamada de métodos sobre eles
•Chamada com o nome da classe em vez do objecto
•A classe main é estática. Repare-se que quando é chamada ainda não existem objectos
public class Financial {
public static double percentOf(double p, double a) { return (p / 100) * a;
} // outros métodos da área financeira
}
double tax = Financial.percentOf(taxRate, total);
Introdução à Programação 2007/08 A. Lopes
Membros de dados estáticos
•Um membro de dados estático pertence à classe, não a um objecto da classe. Denomina-se também campo da classe
public class BankAccount {
...
private double balance;
private int accountNumber;
private static int lastAssignedNumber = 1000; // se não fosse
// estático, cada instância da classe teria o seu próprio valor
}
public BankAccount()
{
// define o próximo número de conta e actualiza o campo estático
lastAssignedNumber++;
// atribui o número do campo actual ao número de conta deste banco
accountNumber = lastAssignedNumber;
}
Introdução à Programação 2007/08 A. Lopes
Inicialização de membros de dados estáticos
(A) Não fazer nada. Neste caso, os campos terão 0 se forem números, false se forem valores booleanos ou null se forem objectos
(B) Inicialização explícita (incluindo a forma pouco usual de bloco)
public class BankAccount {...
// executa uma só vez, quando a classe é carregadaprivate static int lastAssignedNumber = 1000; ...
}
public class BankAccount {...
private static int lastAssignedNumber; static { ... lastAssignedNumber = 1000; }}
Introdução à Programação 2007/08 A. Lopes
Membros de dados estáticos
•Os membros de dados estáticos devem ser sempre declarados como privados. Como excepção a esta regra, temos as constantes estáticas, que podem ser públicas ou privadas
•Não se deve utilizar em demasia os campos estáticos, com excepção das constantes
public class BankAccount
{
...
// a referir como BankAccount.OVERDRAFT_FEE
public static final double OVERDRAFT_FEE = 5;
...
}
Introdução à Programação 2007/08 A. Lopes
Campo estático e campos de instanciação
Introdução à Programação 2007/08 A. Lopes
Abrangência de variáveis locais
•Abrangência de uma variável: região do programa na qual se pode aceder à variável, que vai desde a sua declaração até ao fim do bloco que a engloba
•Por vezes, o mesmo nome de variável é usado em dois métodos distintos. Neste caso, as variáveis em causa são independentes uma da outra, logo as respectivas abrangências são disjuntas, i.e., não se sobrepõem
public class RectangleTester { public static double area(Rectangle rect) { double r = rect.getWidth() * rect.getHeight(); return r; } public static void main(String[] args) { Rectangle r = new Rectangle(5, 10, 20, 30); double a = area(r); System.out.println(r); }}
Introdução à Programação 2007/08 A. Lopes
Abrangência de variáveis locais
•A abrangência de uma variável local não pode conter a definição de outra variável com o mesmo nome
•Mas podem coexistir variáveis locais com o mesmo nome desde que as respectivas abrangências não se sobreponham
Rectangle r = new Rectangle(5, 10, 20, 30);if (x >= 0) {
double r = Math.sqrt(x); // erro: não pode haver aqui outra variável r ...}
if (x >= 0) { double r = Math.sqrt(x);
...} // termina aqui a abrangência de relse { Rectangle r = new Rectangle(5, 10, 20, 30); // é correcto ter agora
... // uma variável r}
Introdução à Programação 2007/08 A. Lopes
Abrangência de membros da classe
•Os membros de dados privados possuem abrangência de classe: é possível aceder todos os membros em qualquer método da classe
•Um nome de campo ou método não classificado refere-se ao parâmetro this
public class BankAccount
{ public void transfer(double amount, BankAccount other)
{ withdraw(amount); // i.e. this.withdraw(amount);
other.deposit(amount); }
...}
Introdução à Programação 2007/08 A. Lopes
Sobreposição de abrangência
•Uma variável local pode sobrepor-se a um campo com o mesmo nome. Isto porque a abrangência local prevalece sobre a abrangência de classe
•O acesso a campos “ensombrados” será feito através da sua classificação com a referência this
public class Coin {
private String name; private double value; // campo
... public double getExchangeValue(double exchangeRate)
{ double value; // variável local com o mesmo nome
... return value;
}}
value = this.value * exchangeRate;
Introdução à Programação 2007/08 A. Lopes
Organização de classes em pacotes
•Um pacote é um conjunto de classes relacionadas entre si. Para incluir uma classe num pacote, o ficheiro dessa classe deve conter como primeiro instrução
•O nome de um pacote define-se através de um ou mais identificadores separados por pontos. Por exemplo:
package nomePacote;
package ipb.exercicios;
// classe IdentityCard pertence ao pacote ipb.exercicios
public class IdentityCard{
...}
Introdução à Programação 2007/08 A. Lopes
Organização de classes em pacotes
Pacote Objectivo Exemplo
java.lang Suporte da linguagem Math
java.util Utilitários Random
java.io Entrada e saída PrintScreen
Java.awt Abstract Windowing Toolkit Color
java.applet Applets Applet
java.net Rede Socket
java.sql Acesso a base de dados ResultSet
java.swing Swing user interface JButton
Introdução à Programação 2007/08 A. Lopes
Especificação de pacote
package packageName ;
Exemplo:
package ipb.exercicios;
Objectivo:
Para declarar que todas as classes do ficheiro pertencem a um determinado pacote
Introdução à Programação 2007/08 A. Lopes
Importação de pacotes
•A utilização de uma classe pertencente a um pacote pressupõe a sua importação
•A importação de todas as classes de um pacote pode ser feita através de uma única instrução
•Uma classe pode ser utilizada sem importação, desde que se especifique na íntegra a sua proveniência
•Não é necessário importar classes do pacote java.lang, nem classes que pertencem ao mesmo pacote
java.util.Scanner in = new java.util.Scanner(System.in);
import java.util.Scanner;...Scanner in = new Scanner(System.in)
import java.util.*;
Introdução à Programação 2007/08 A. Lopes
Nomes de pacotes e localização das classes
•A utilização de pacotes permite evitar conflitos de nomes
•Os nomes dos pacotes não devem ser ambíguos e devem ser concordantes com o nome do caminho das directorias da respectiva localização
•O caminho de uma classe inclui a directoria base que possa conter as directorias do pacote
java.util.Timer vs. javax.swing.Timer
package com.horstmann.bigjava