cap tulo 9 desenho de classes - universidade nova de lisboa

13
Capítulo 9 Desenho 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

Upload: others

Post on 12-Nov-2021

2 views

Category:

Documents


0 download

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