Você está na página 1de 3

Associações entre classes

Diagrama conceitual
Como vimos em sala de aula, em um projeto orientado a objetos as classes de software representam conceitos do
domínio da aplicação. Ocorre que, muitas vezes, para recuperar informação espalhada pelas classes é preciso criar
associações em software entre conceitos relacionados. Vamos usar como exemplo um domínio conhecido por nós,
uma biblioteca, e vamos tentar criar um diagrama dos conceitos envolvidos na operação de emprestar um livro. Este
diagrama é chamado de um diagrama conceitual.

Figura 1

É fácil entender a necessidade das associações entre os conceitos, conforme mostrado na figura. Imagine que o
software tem de fornecer o nome do usuário que pegou emprestado um exemplar de um livro do qual se conhece
um título. Nesse caso, é preciso navegar pelas associações para, a partir do Livro, chegar ao Exemplar e deste ao
Empréstimo, e deste ao Usuário.
O passo seguinte é determinar a multiplicidade das associações.

Multiplicidade das associações


A multiplicidade das associações define o número de instâncias que participam de uma associação entre classes.
Essa informação é importante para determinar se uma associação é opcional ou obrigatória (um livro pode existir
sem exemplares?) e o tipo de variável que deve ser usada para armazenar a associação (um exemplar é um exemplar
de um livro, logo uma única referência deve ser suficiente para armazenar a associação. Por outro lado, um livro
pode ter vários exemplares, logo é preciso uma coleção de referências – um List Python – para armazenar a
associação). A multiplicidade pode ter um dos seguintes valores:
1 associação obrigatória, uma instância associada.
0..1 associação opcional, zero ou uma instâncias associadas
0..* associação opcional, zero ou muitas instâncias associadas
* associação opcional, zero ou muitas instâncias associadas
1..* associação obrigatória, uma ou muitas instâncias associadas

Vamos tentar determinar as multiplicidades das associações na Figura 1.


Associação entre Usuário e Empréstimo: um usuário está associado a zero ou muitos empréstimos, um empréstimo
está associado a um usuário.
Associação entre Empréstimo e Exemplar: um empréstimo está associado a um exemplar, um exemplar está
associado a zero ou muitos empréstimos (o empréstimo atual e o histórico de empréstimos passados)
Associação entre Exemplar e Livro: um exemplar está associado a um livro, um livro está associado a zero ou muitos
exemplares.
O diagrama conceitual, com as multiplicidades assinaladas, ficaria então:

Figura 2

Sentido das associações


O próximo passo é determinar o sentido das associações, isto é, elas são unidirecionais? Em que sentido? Ou elas
são bidirecionais? O que determina o sentido de uma associação são as perguntas que o sistema de informação terá
de responder. É preciso, a partir de uma instância de livro, chegar aos exemplares associados? E o caminho
contrário, de um exemplar para o livro, é necessário? Somente os especialistas no domínio podem responder a essas
perguntas. Uma associação não deveria ser projetada como bidirecional onde uma associação bidirecional seria
suficiente. Uma associação bidirecional requer variáveis nos dois lados da associação para armazenar as referências.
Além disso, é necessário garantir a integridade da associação bidirecional, isto é, se o objeto A referencia o objeto B,
então o objeto B tem de referenciar o objeto A.
No caso do nosso exemplo, a Biblioteca, conhecemos razoavelmente o domínio para perceber que todas as
associações na Figura 2 são provavelmente bidirecionais. O diagrama de classes, com o sentido das associações
assinalado, fica então:

Figura 3

Implementação das associações


É preciso agora escolher as variáveis que armazenarão as associações. A regra é simples: multiplicidade máxima igual
a 1 é armazenada em uma variável simples, multiplicidade máxima igual a * é armazenada em um List Python.

Figura 4

Vamos escrever o código Python das classes Livro e Exemplar. Foram acrescentados alguns métodos úteis para o
teste das classes.
class Exemplar:
def __init__(self, codigo, livro):
self.__codigo = codigo
# associação obrigatória com livro
self.__livro = livro
# associação opcional com empréstimos
self.__emprestimos = []
# livro, me adiciona na sua coleção!
livro.addExemplar(self)

def getCodigo(self):
return self.__codigo

class Livro:
def __init__(self, titulo, ISBN):
self.__titulo = titulo
self.__ISBN = ISBN
# associação opcional com exemplares
self.__exemplares = []

def addExemplar(self, exemplar):


self.__exemplares.append(exemplar)

def getCodigosExemplares(self):
lista = []
for exemplar in self.__exemplares:
lista.append(exemplar.getCodigo())
return lista
E agora um código de teste, que usa as classes Livro e Exemplar
# livros é um dicionário de ISBN em Livro
livros = {}

# um livro é criado sem exemplares


livros['978-85-7780-013-1'] = Livro(titulo='Aprendendo Python',
ISBN='978-85-7780-013-1')

# cadastra o primeiro exemplar de "Aprendendo Python"


Exemplar(codigo='123.4567-890', livro=livros['978-85-7780-013-1'])

# cadastra outro exemplar de "Aprendendo Python"


Exemplar(codigo='123.4567-645', livro=livros['978-85-7780-013-1'])

print livros['978-85-7780-013-1'].getCodigosExemplares()

Observe na classe Exemplar o padrão usado para garantir a integridade das associações bidirecionais, um dos lados
da associação é responsável pela inclusão das referências em ambos os lados da associação. Evita-se assim deixar a
responsabilidade da associação mútua para o programador usuário da classe.

Você também pode gostar