Sei sulla pagina 1di 74

Modelo de classes de projeto

(notação e conceitos relevantes)


Prof. Eduardo Bezerra

Perfection (in design) is achieved not when there is nothing more to add, but
rather when there is nothing more to take away.
Eric Raymond, The Cathedral and the Bazaar
Introdução
• O modelo de classes de projeto
– é resultante de refinamentos no modelo de
classes de domínio.
– é construído em paralelo com o modelo de
interações de projeto.
– contém detalhes úteis para a implementação dos
elementos (classes, interfaces, associações, etc)
nele contidas.

2
Visão geral
• Notação adicional da UML para o MCP
– Atributos, operações, parâmetros, associações, ...
• Conceitos envolvidos:
– dependências, navegabilidade das associações
– classes abstratas, operações abstratas
– interfaces,
– herança de implementação e de interface
– polimorfismo, reescrita, sobrecarga

3
Atributos, operações e parâmetros

4
Atributos, operações e parâmetros

5
Dependências
• Uma dependência é um relacionamento entre
dois elementos, indicando que a especificação
ou a implementação de um elemento (cliente)
usa o outro (fornecedor).
• Há vários tipos de dependência: por atributo,
por variável global, por variável local, por
parâmetro, ...

6
Dependências
• Dependência por atributo (ou dependência
estrutural): o dependente possui um atributo
que é uma referência para o outro elemento
do qual o primeiro depende.
• Dependência por variável global: um objeto
de escopo global é referenciado em algum
método da classe dependente.

7
Dependências
• Dependência por variável local: um objeto
recebe outro como retorno de um método, ou
possui uma referência para o outro objeto
como uma variável local em algum método.
• Dependência por parâmetro: um objeto
recebe outro como parâmetro em um
método.
• A lista não acaba aqui!

8
Dependências
• Na UML, uma dependência é representada por uma
linha tracejada entre os elementos envolvidos.
– O sentido é do elemento dependente (cliente) para o
elemento do qual ele depende (fornecedor).

9
Fonte da figura: Utilizando UML e Padrões, 3ª ed., Larman
Interfaces
• Uma interface é um classificador que define
um contrato de comportamento.
– Este contrato compreende um conjunto de
operações.
• Classes que implementam (realizam) uma
interface devem fornecer métodos para todas
as operações especificadas na interface.

10
Interfaces
• Interfaces são úteis para:
– Capturar semelhanças de comportamento entre
classes, sem forçar relacionamentos gen/espec
entre elas.
– Declarar operações que uma ou mais classes
devem implementar (obrigatoriamente).
– Revelar as operações de um objeto, sem revelar
sua classe.

11
Interfaces (notação)
public interface ElementoDiagrama {
double PI = 3.1425926; //constant.
void desenhar();
void redimensionar();
}

public class Circulo implements ElementoDiagrama {



public void desenhar() { /* draw a circle*/ }
public void redimensionar() { /* draw a circle*/ }
}

public class Retangulo implements ElementoDiagrama {



public void desenhar() { /* draw a circle*/ }
public void redimensionar() { /* draw a circle*/ }
}

12
Interfaces publicadas e requeridas
• Uma classe tanto pode publicar interfaces,
quanto pode requerer interfaces.
– interface publicada (published interface)
– interface requerida (required interface)
• Novas notações adicionadas na UML 2:

13
Interfaces publicadas e requeridas
• Os dois fragmentos de diagrama abaixo são
equivalentes.

14
Navegabilidades
• Associações, agregações e composições
podem ser de dois tipos:
– Bidirecionais
– Unidirecionais
• A escolha do sentido da navegabilidade pode
ser feita através da construção do modelo de
interações.
– Se A envia uma mensagem para B, deve haver
uma navegabilidade de A para B.

15
Navegabilidades

16
Fonte da figura: UML 2 Certification Guide
Implementação de associações
• Toda associação definida entre classes deve ser
implementada (i.e., refletida no código fonte).
• Há vários casos a considerar na implementação
de associações, em função da conectividade:
– 11
– N1
– 1N
– NM

17
Conectividades 11 e N1
• Se existe uma associação 11 ou N1 entre
as classes A e B, no sentido de A para B,
definimos um atributo do tipo B em A.
• Exemplo:

public class Professor {


private GradeDisponibilidade grade;
...
}

18
Conectividade 1N
• Para uma associação 1N entre A e B , no
sentido de A para B, definimos um atributo do
tipo Coleção<B> em A.
public class Aluno {
private Set<Participacao> participacoes;
...
public boolean adicionarParticipacao(...){
...
participacoes.add(...)
...
}
public boolean removerParticipacao(...) {
...
participacoes.add(...)
...
}
19
}
Conectividade NM
• A implementação de associações NM é a mesma do
caso de associações 1 N.

public class GradeDisponibilidade {


private Set<Disciplina> disciplinas;
...
}
20
Classes abstratas
• Usualmente, a existência de uma classe se justifica
pelo fato de haver a possibilidade de gerar instâncias
a partir da mesma.
– Essas classes são chamadas de classes concretas.
• No entanto, pode haver classes que não geram
instâncias diretamente.
– Note o uso da palavra “diretamente”.
– Essas classes são chamadas de classes abstratas.

21
Operações abstratas
• Uma classe pode possuir operações abstratas
e operações concretas.
• Uma operação abstrata é aquela que não
possui método (implementação).
• Na UML, uma operação abstrata é
representada de duas maneiras alternativas:
1. Com sua assinatura em itálico.
2. Qualificando-a sua assinatura com a propriedade
{abstract}

22
Classes e operações abstratas
• Exemplo: no diagrama abaixo, aplicarJuros é
uma a operação abstrata em ContaBancaria,
uma classe abstrata.

23
Operações polimórficas
• Uma subclasse herda todas as propriedades de
sua superclasse que tenham visibilidade pública
ou protegida.
• Entretanto, pode ser que o comportamento de
alguma operação herdada deva ser diferente para
a subclasse.
– Nesse caso, a subclasse deve redefinir (reescrever) o
comportamento da operação.
– A assinatura da operação é reutilizada na subclasse.
– A implementação da operação (método) é diferente.

24
Operações polimórficas
• São operações de mesma assinatura definidas em
diversos níveis de uma hierarquia gen/spec e que
possuem comportamento (método) diferente.
– assinatura é repetida na(s) subclasse(s) para enfatizar
a redefinição de implementação.
• Objetivo: garantir que as subclasses tenham uma
interface em comum.
• Operações polimórficas implementam o princípio
do polimorfismo no qual dois ou mais objetos
respondem a mesma mensagem de formas
diferentes.
25
Operações polimórficas (exemplo)
• O método da operação getArea em Circulo é
diferente do método da mesma operação em
Retangulo.

26
Operações polimórficas (exemplo)
• Operações polimórficas não necessariamente
envolvem operações abstratas.
Funcionário
-salárioBase : Moeda
+obterPagamento() : Moeda
return salárioBase; +definirSalárioBase(in umSalario : Moeda)
+obterSalárioBase() : Moeda

Vendedor
return comissão * obterSalárioBase(); -comissão : Porcentagem
+obterPagamento() : Moeda
27
Tipos parametrizados
• Um tipo parametrizado é aquele utilizado
para definir outras tipos.
• Possui operações ou atributos cuja definição é
feita em função de um ou mais parâmetros.
• Há duas notações possíveis na UML para
representar um tipo parametrizado:

28
Tipos parametrizados

29
Fonte da figura: Utilizando UML e Padrões, 3ª ed., Larman
Tipos parametrizados
• Uma coleção pode ser definida a partir de um
tipo parametrizado, onde o parâmetro é o tipo
de cada elemento da coleção.

30
Atributos e operações estáticas
• Atributos estáticos (variáveis de classe) são
aqueles cujos valores valem para a classe de
objetos como um todo.
• Operações estáticas são as que não precisam
da existência de uma instância da classe a qual
pertencem para serem executadas.
– Chamada: NomeClasse.Método(parâmetros)

31
Sobrecarga de métodos
• Definição (métodos sobrecarregados): são
métodos (próprios ou herdados) em uma
classe que possuem o mesmo nome, mas que
diferem entre si pela lista de parâmetros.
• Sua chamada é determinada a tempo de
compilação.
• Termos originais relevantes:
– Method overloading, overloaded methods; static
polymorphism(termo polêmico...); early binding.

32
Sobrecarga de métodos
• No exemplo a seguir, a subclasse possui dois
métodos sobrecarregados.

33
Sobrecarga de métodos

Fonte: http://www.coderanch.com/t/411726/Beginning-Java/java/Overloading-vs-Polymorphism 34
Reescrita de métodos
• Definição (reescrita de métodos): é o processo
de implementação de operações polimórficas.
• A chamada de uma operação polimórfica é
determinada apenas a tempo de execução.
• Termos originais relevantes:
– Method overriding; overrided method; dynamic
polymorphism; late binding.

35
Reescrita de métodos

Fonte: http://www.coderanch.com/t/411726/Beginning-Java/java/Overloading-vs-Polymorphism 36
Herança de comportamento
• No exemplo a seguir, as subclasses herdam
comportamento(método speak) de sua
superclasse.

37
Herança de interface (1/2)
• No exemplo a seguir, as subclasses herdam
interface(operação aplicarJuros) de sua
superclasse.
– Herdam também comportamento (através dos
métodos debitar e creditar).

38
Herança de interface (2/2)
• No exemplo abaixo, também há herança de
interface.

39
Material complementar
Princípio de Substituição de Liskov
• Liskov Substitution Principle (LSP), por Barbara Liskov,
em 1993.
• Princípio: todas as classes derivadas de uma classe
devem ser trocáveis quando usadas como a classe
base.
• Contexto:
– Seja A uma classe e B uma de suas subclasses. Seja ainda o
método m(A a) { … }
– Se m se comporta corretamente quando o parâmetro é
uma instância de A, ele deve se comportar corretamente
quando o parâmetro é uma instância de B
– Isso sem que m precise saber que existe a classe B

41
LSP – exemplo clássico
• Seja a classe abaixo.
class Retangulo {
protected double l, h;
protected Point topEsquerdo;
public double setAltura(double x) { h=x; }
public double setComprimento(double x) { l=x; }
public double getAltura() { return h; }
public double getComprimento() { return l; }
public double area() { return h*l; }

}
• Suponha que haja várias aplicações clientes dessa classe…

42
LSP – exemplo clássico (cont.)
• Adicionando quadrados à aplicação…
• Um quadrado é um tipo de retângulo, certo?
• Então:
– class Quadrado extends Retangulo { … }
• A princípio, não precisamos modificar o código cliente
pré-existente.
– e.g., void m(Retangle x) { … } não precisa de modificações
quando da adição dessa nova classe Quadrado.
• Mas, há problemas com essa solução…podemos
“degenerar” um quadrado!
– Podemos criar um quadrado de comprimento e altura
diferentes.

43
LSP – exemplo clássico (cont.)
• Uma segunda solução: redefinir os métodos setAltura e
setComprimento na classe Quadrado. Veja a seguir.
class Quadrado extends Retangulo {
public void setAltura(double x) {
h=x; l=x;
}
public void setComprimento(double x) {
h=x; l=x;
}
}
• Que tipo de herança é esse que estamos usando aqui?

44
LSP – exemplo clássico (cont.)
• Considere agora o trecho de código (cliente) a seguir:
void m(Retangulo r) {
r.setAltura(5);
r.setComprimento(4);
assert (r.area() == 20);
}
• Quando temos apenas objetos retângulo, o código
acima é válido; no entanto, este código não é válido
quando, além de retângulos, temos também
quadrados.
• Não há nada de errado com o método m
• O que está errado em Quadrado?
45
O papel do LSP
• LSP é um princípio bastante restritivo. Em geral,
deve ser usado como um sinalizador
– É possível e aceitável que se viole esse princípio, mas
a violação deve ser examinada cuidadosamente.
• Depende do cliente da hierarquia de classes
– e.g., se temos um programa no qual altura e
comprimento nunca são modificados, é aceitável ter
um Quadrado como uma subclasse de Retangulo.
• “Square subclass of Rectangle” e “Elipse subclass
of Circle” têm sido fontes de guerras religiosas na
comunidade OO por anos (vide http://ootips.org)

46
Projeto de métodos
• Métodos de construção e destruição de objetos
• Métodos de acesso (getX/setX) ou propriedades
• Métodos de ligação para adicionar (e remover)
ligações (conexões) entre objetos a tempo de
execução.
• Outros métodos:
– valores derivados,
– formatação, conversão,
– cópia e clonagem de objetos, etc.

47
Métodos de acesso vs encapsulamento
• Princípio do encapsulamento: qualquer acesso
a informações internas a um objeto deve ser
realizado através de sua interface.
– A interface de um objeto é definida pelas operações
de visibilidade pública existentes em sua classe.

48
Métodos de acesso vs encapsulamento
• Para assegurar o encapsulamento da classe, é
adequado que haja operações para obter
acesso (seletor) e para modificar o valor
(modificador) de cada atributo dos objetos
dessa classe.

49
Metodos de Ligação (exemplo)
public class Departamento {

private Set<Empregado> empregados = new HashSet();

public void adicionarEmpregado(Empregado empregado) {
this.empregados.add(empregado);
}
public boolean removerEmpregado(Empregado empregado) {
return this.empregados.remove(Empregado);
}
public Set getEmpregados () {
return Collections.unmodifiableSet(this.empregados);
}
}

50
Tipos parametrizados
• Uma coleção pode ser definida a partir de uma
classe parametrizada, onde o parâmetro é o
tipo do elemento da coleção.
• Há duas notações possíveis na UML para
representar uma classe parametrizada:
Tipo
Lista Lista<Tipo>

51
Operações abstratas
• Exemplo: Círculo e Quadrado são classes concretas, pois
fornecem implementação para a operação area().

Operação abstrata. Subclasses


FiguraGeométrica devem implementar o
+desenhar() comportamento desta operação.

Círculo Quadrado
+desenhar() +desenhar()

52
Especificação de atributos

53
Atributos e operações estáticas
• Atributos estáticos (variáveis de classe) são aqueles
cujos valores valem para a classe de objetos como um
todo.
• Operações estáticas são as que não precisam da
existência de uma instância da classe a qual pertencem
para serem executadas.
– Chamada: NomeClasse.Método(parâmetros)

54
Diagrama de classes de projeto -
exemplo

55
Fonte: Introduction to UML 2.0, Terry Quatrani
Diagrama de classes de projeto -
exemplo

56
Fonte: Introduction to UML 2.0, Terry Quatrani
Notação para interfaces

57
Fonte: Introduction to UML 2.0, Terry Quatrani
Especificação de atributos e operações
• Na UML, a especificação completa para
atributos, operações e parâmetros tem as
sintaxes abaixo, respectivamente:

[/] [visibilidade] nome [multiplicidade] [: tipo] [= valor-inicial]

[visibilidade] nome [(parâmetros)] [ : tipo-retorno] [{propriedades}]

[nome-direção] [nome] : tipo [=valor-default]


58
Enumerações (Enumerations)
• Um tipo enumerado é definido em UML com o
estereótipo <<enumeration>>

Fonte da figura: UML Distilled, 3ª ed., Fowler 59


Definição de restrições

60
Fonte da figura: Utilizando UML e Padrões, 3ª ed., Larman
Definição de restrições
• Três modos alternativos de definir restrições
sobre elementos de um MCP.

61
Fonte da figura: Utilizando UML e Padrões, 3ª ed., Larman
Restrições sobre associações
• Restrições aplicáveis sobre associações:
– {ordered} versus {unordered}
– {unique} versus {nonunique}
• {unordered} e {unique} são o default.
• Essas restrições condicionam o tipo de dados
usado e a forma de implementar a associação.

62
Notas explicativas
• Notas explicativas podem ser usadas para
fornecer detalhes sobre métodos ou atributos.

63
Fonte da figura: Utilizando UML e Padrões, 3ª ed., Larman
Classes ativas
• São classes que possuem uma linha de
execução (thread) independente.
• No exemplo a seguir, Clock é uma classe ativa.

64
Associações como atributos
• Associações de uma classe podem ser
representadas alternativamente como
atributos.

65
Fonte da figura: UML Distilled, 3ª ed., Fowler
Associações como atributos
• O diagrama abaixo apresenta a mesma
informação contida no diagrama anterior.

66
Fonte da figura: UML Distilled, 3ª ed., Fowler
Interface (em Java)
• Em Java, interfaces são definidas de forma
semelhante a classes.
– Contudo, a palavra chave interface é utilizada em
vez de class.
– Outra diferença é que todas as declarações têm a
mesma visibilidade em um interface: pública.
– Adicionalmente, uma interface pode possuir
apenas atributos estáticos.

67
Navegabilidade unidirecional
• Indica que apenas um dos extremos da
associação tem ciência da existência da
mesma.
• Representada na UML através da adição de
um sentido à seta da associação.

68
Navegabilidade bidirecional
• Indica que há um conhecimento mútuo entre
os objetos associados.
• Representada na UML através da adição de
um sentido a cada um dos extremos da linha
da associação.

69
Fonte da figura: UML Distilled, 3ª ed., Fowler
Operações polimórficas
• Operações polimórficas facilitam a
implementação, pois:
– Se duas ou mais subclasses implementam uma mesma
operação polimórfica, a mensagem a ser passada para
ativar essa operação é a mesma para todas essas
classes.
– No envio da mensagem, o remetente não precisa
saber qual a verdadeira subclasse de cada objeto, pois
eles aceitam a mesma mensagem.
– A diferença é que o método que implementa a
operação é diferente em cada subclasse.

70
Dependências
Dependências na UML 2

72
Dependências
• Estereótipos predefinidos podem ser usados
para rotular dependências: <<use>>,
<<create>>, <<call>>, <<realize>>, ...

73
Fonte da figura: Utilizando UML e Padrões, 3ª ed., Larman
Dependências - exemplos

74
Fonte da figura: UML 2 Certification Guide

Potrebbero piacerti anche