Programação com Objectos Processamento de Dados I 3. UML (Unified Modeling Language) 1
Modelo UML Diagrama de classes Programação com Objectos / Processamento de Dados I 2
Modelo O desenvolvimento de programas orientados aos objectos assenta na construção de um modelo. O modelo é uma abstracção dos aspectos essenciais do problema. O modelo estrutura o problema e permite detectar omissões e inconsistências. O modelo é um passo intermédio entre o enunciado do problema e a solução. Um sistema de análise descreve os modelos (i.e., representações limitadas) da aplicação a desenvolver. Aumenta a legibilidade (menos informação que o código, permitindo visualizar globalmente a aplicação). Mostra a estrutura da aplicação, sem detalhes de implementação. A representação gráfica incrementa a clareza semântica. Devido à complexidade, a abordagem OO é descrita por vários modelos, onde cada modelo aborda um aspecto particular. Programação com Objectos / Processamento de Dados I 3
UML UML - Unified Modeling Language resulta da fusão de vários sistemas de análise: Booch (G. Booch) OOSE (I. Jacobson) OMT (J. Rumbaugh) 1ª proposta divulgada em 1997 (1999 -v1.1, 2000 -v1.3, 2001 -v1.4, 2003 -v1.5, Abril 2004 -v2.0) Ferramentas de desenho UML: Rational Rose ArgoUML(http://argouml.tigris.org/) (gratuito) Programação com Objectos / Processamento de Dados I 4
UML Em UML os modelos de software são representados por um conjunto de diagramas Estes são criados e utilizados durante a fase de análise e, posteriormente, como ferramenta de comunicação com os programadores Os modelos são constituídos por objectos (com os seus atributos e comportamentos) que interactuam entre si através do envio de mensagens Programação com Objectos / Processamento de Dados I 5
UML UML v2 disponibiliza 13 diagramas, agrupados em: Modelação estrutural (pacotes, classes, objectos, estrutura composicional, componentes, aplicação física). Modelação de comportamento (use case, actividade, máquina de estados, comunicação, sequência de mensagens, temporização, enquadramento das interacções). Programação com Objectos / Processamento de Dados I 6
Diagrama de classes Um diagrama de classes dá uma panorâmica geral do sistema, mostrando as suas classes e as relações entre elas. Os diagramas de classe são estáticos, ou seja mostram o que interage, mas não o que acontece quando a interacção acontece Apenas relações estáticas: que classes constituem outra, que classes uma dada classe conhece e usa, etc. A identificação dessas classes e suas relações no enunciado do problema tem de ser feita previamente. O diagrama de classes é um grafo: Os nós são classes de objectos Os arcos são relações entre essas classes Programação com Objectos / Processamento de Dados I 7
Diagrama de classes Representação das classes Uma classe é representada por um rectângulo dividido em três secções: Identificador (nome da classe); Atributos; Métodos. Identificador Atributos Métodos Pessoa nome: String numtelefone: long numbi: long getnome (): String getnumtelefone (): long getnumbi (): long setnome (nome:string) setnumtelefone (numtelefone:long) setnumbi (numbi: long) Programação com Objectos / Processamento de Dados I 8
Diagrama de classes Representação dos membros da classe Especificação dos atributos: [visibilidade] nome :tipo [multiplicidade] [=valor por omissão] + public - private # protected ~ package Especificação dos métodos: [visibilidade] nome (lista dos argumentos:tipo) [:tipo de retorno] OBS: Os atributos e métodos de classe (static) são sublinhados. Programação com Objectos / Processamento de Dados I 9
Diagrama de classes Representação da classe Conta Conta - saldo: float - titular: Pessoa - numcontas: int + settitular (titular: Pessoa) + setsaldo (saldo: float) + gettitular (): Pessoa + levantamento (valor: float) + deposito (valor: float) + consultarsaldo (): float - incnumcontas () - decnumcontas() Programação com Objectos / Processamento de Dados I 10
UML Representação dos objectos da classe Um objecto de uma classe é representado por um rectângulo dividido em duas secções: Nome_do_objecto: nome_da_classe Valores_dos_atributos person: Pessoa nome: Ana Maria numtelefone: 296123456 numbi: 123456789 Programação com Objectos / Processamento de Dados I 11
Exercício Observe com atenção a seguinte sequência de imagens Programação com Objectos / Processamento de Dados I 12
Programação com Objectos / Processamento de Dados I 13
Programação com Objectos / Processamento de Dados I 14
Programação com Objectos / Processamento de Dados I 15
Programação com Objectos / Processamento de Dados I 16
Programação com Objectos / Processamento de Dados I 17
Programação com Objectos / Processamento de Dados I 18
Programação com Objectos / Processamento de Dados I 19
Algumas questões O que visualizamos nas imagens anteriores? Portas Como podemos caracterizar então uma porta? Atributos Para além das suas características o que diferencia as portas apresentadas? Estados Programação com Objectos / Processamento de Dados I 20
Estados de uma porta Fechada fechar trancar abrir destrancar Aberta Trancada Programação com Objectos / Processamento de Dados I 21
Solução 1: Classe Porta Porta - aberta: boolean -- fechada: boolean -- trancada: boolean + Porta (open: boolean, closed:boolean, locked:boolean) + setestado (open: boolean, closed:boolean, locked:boolean): void + isaberta():boolean + isfechada(): boolean +istrancada():boolean Programação com Objectos / Processamento de Dados I 22
Solução 2: Classe Porta Porta - aberta: boolean -- fechada: boolean -- trancada: boolean + Porta (open: boolean, closed:boolean, locked:boolean) + abrir (): void + fechar(): void + trancar(): void + isaberta():boolean + isfechada(): boolean +istrancada():boolean Programação com Objectos / Processamento de Dados I 23
Solução 3: Classe Porta Porta - estado: String + Porta (estado: String) + setestado (estado: String): void + getestado(): String + isaberta():boolean + isfechada(): boolean +istrancada():boolean Programação com Objectos / Processamento de Dados I 24
Solução 4: Classe Porta Porta - estado: int + Porta (estado: int) + abrir() :void + fechar() :void + trancar() :void + destrancar():void + isaberta(): boolean + isfechada(): boolean +istrancada():boolean Programação com Objectos / Processamento de Dados I 25
UML Relações entre objectos Os objectos não vivem isolados e nos programas são estabelecidas relações de cooperação. Uma relação não é mais do que uma conexão entre elementos. Existem diferentes tipos de relações: Associação: relaciona objectos entre si. Composição/Agregação: relação que denota o todo constítuido por partes. Herança: mecanismo de generalização especialização de classes. Realização: uma classe implementa a funcionalidade definida numa interface. Programação com Objectos / Processamento de Dados I 26
UML Associação Uma associação representa uma relação semântica entre as classes participantes da relação: Podem ter um nome (etiqueta) - pode ter uma seta que indica a direcção em que o nome deve ser lido O número de objectos que podem participar na associação O papel que cada classe desempenha na associação Uma associação entre classes é representada através de uma linha. Programação com Objectos / Processamento de Dados I 27
UML Especificação da associação Cada associação tem dois papéis; Os papéis fazem parte da associação e não da classe, porque uma mesma classe pode ter diferentes papéis em diferentes associações Classe A papel de A etiqueta papel de B Classe B Empresa empregador Trabalha para empregado Pessoa Programação com Objectos / Processamento de Dados I 28
UML Especificação da associação A multiplicidade de uma associação traduz o nº de instâncias de uma classe que se podem associar com uma única instância das restantes classes. 1: Uma única instância 0..1: zero ou uma instância * ou 0..*: zero ou mais instâncias n..*: n ou mais instâncias 5..10: 5 a 10 instâncias (temos instâncias mais complexas) Classe A multiplicidade de A papel de A etiqueta multiplicidade de B papel de B Classe B Empresa 1 Trabalha para 1..* empregador empregado Pessoa Programação com Objectos / Processamento de Dados I 29
UML Classes de associações Uma associação pode ser ela própria descrita como uma classe classe associativa. O identificador da associação para a ser o nome da classe. 1 1..* empregador empregado Programação com Objectos / Processamento de Dados I 30
UML Associações reflexivas São associações entre objectos da mesma classe. Os papéis são fundamentais neste caso pois são eles que permitem perceber a associação existente. Programação com Objectos / Processamento de Dados I 31
UML Agregação/Composição A agregação é uma associação, que denota uma relação do todo ser formado por partes. A agregação é dita como sendo uma relação de has-a. Representada como uma associação com um pequeno diamante não preenchido no extremo relativo ao todo. Programação com Objectos / Processamento de Dados I 32
UML Agregação/Composição Na composição, o desaparecimento do todo conduz ao desaparecimento das partes. Representada como uma associação com um pequeno diamante preenchido no extremo relativo ao todo. Programação com Objectos / Processamento de Dados I 33
UML Agregação/Composição De uma maneira geral tanto a agregação como a composição não têm identificador, pois o significado destas relações está representada pelo próprio par todo-partes. A multiplicidade deve aparecer em ambos os extremos. Quando a multiplicidade é omitida, considera-se que é exactamente 1. Programação com Objectos / Processamento de Dados I 34
Exercício Considere a seguinte situação: 1 banco tem vários clientes. Cada cliente pode ter 1 ou várias contas, sendo o cliente o seu titular. Para existir uma conta deve de estar sempre afecta a um cliente (o seu titular), podendo no entanto ter outros dois clientes como titulares secundários. Descreva um diagrama de classes e inclua as suas relações. Programação com Objectos / Processamento de Dados I 35
UML Herança Princípio Aberto-Fechado Fecho: devem estar desenvolvidos para que o programa possa ser usado sem alterações. Abertura: classes devem estar abertas para extensão, por forma a incorporar alterações com o mínimo impacto no sistema. Programação com Objectos / Processamento de Dados I 36
UML Herança A herança é um mecanismo em que a subclasse constitui uma especialização da superclasse. A superclasse pode ser vista como generalização das subclasses. A herança é dita como uma relação is-a. As subclasses herdam os atributos e métodos das superclasses. Novos atributos e métodos podem ser adicionados às subclasses. O polimorfismo é a redefinição de métodos, da superclasse nas subclasses, com a mesma assinatura. Em POO o polimorfismo é normalmente implementado através de ligação dinâmica (o método a ser executado é determinado apenas em tempo de execução). Programação com Objectos / Processamento de Dados I 37
UML Herança Vantagens da herança: Maior legibilidade, pois as superclasses descrevem os aspectos comuns. Facilita alterações, porque normalmente estas incidem apenas nos aspectos particulares. Promovem a reutilização do código das superclasses. Inconvenientes da herança: Obriga à detecção dos aspectos comuns. Programação com Objectos / Processamento de Dados I 38
UML Herança Na herança simples cada subclasse tem apenas uma superclasse (directa). Na herança múltipla uma subclasse pode ter mais do que uma superclasse (directa). Problema do diamante Programação com Objectos / Processamento de Dados I 39
UML Herança A herança simples é representada por uma seta não preenchida das subclasses para a superclasse. Programação com Objectos / Processamento de Dados I 40
UML Herança A herança múltipla é representada por uma seta não preenchida da subclasse para as superclasses. Programação com Objectos / Processamento de Dados I 41
UML Herança Classe não extensível Classe sem superclasses: representada com a propriedade {root} escrita por baixo do identificador da classe. Classe sem subclasses: representada com a propriedade {leaf} escrita por baixo do identificador da classe. Programação com Objectos / Processamento de Dados I 42
UML Herança O UML permite ainda especificar que um determinado método que não pode ser redefinido em subclasses. Tais métodos são representados com a propriedade {leaf} escrita depois da assinatura do método. Programação com Objectos / Processamento de Dados I 43
EXERCÍCIO: Venda de bebidas Considere uma loja cuja área de negócio é a venda de bebidas. A loja vende dois tipos de bebidas: cerveja e whisky. Estas bebidas são engarrafadas pela própria loja, sendo a loja responsável por manter a quantidade disponível de cada bebida para vender. Para cada tipo de bebida as garrafas comercializadas poderão ser de: - Cerveja: 25 cl, 33 cl e 1 L. - Whisky: apenas de 75 cl. Programação com Objectos / Processamento de Dados I 44
EXERCÍCIO: Funcionalidade da loja Quando se cria uma nova loja é necessário indicar o seu nome, e as capacidades iniciais (em litros) disponíveis de cerveja e whisky, respectivamente. A qualquer momento é possível saber as quantidades disponíveis para venda de qualquer uma das bebidas através dos seguintes métodos: capcerveja e capwhisky. Também é possível obter o nome da loja através do método nomeloja. A loja permite a venda de garrafas de cerveja (método vendecerveja, o qual devolverá a garrafa de cerveja pretendida), tendo que ser indicada a capacidade pretendida da garrafa a vender. Deve imprimir a seguinte mensagem: Loja <nome da loja> vendeu garrafa de cerveja de " <capacidade da garrafa> " cl. A loja permite também a venda de garrafas de whisky (método vendewhisky, o qual devolverá a garrafa de whisky pretendida). Deve imprimir a seguinte mensagem: Loja <nome da loja> vendeu garrafa de whisky. Programação com Objectos / Processamento de Dados I 45
EXERCÍCIO: Funcionalidade da loja Em qualquer um dos casos, se a capacidade disponível da bebida escolhida for inferior à quantidade a vender, então o método de venda invocado deve retornar a referência para objecto null. Finalmente, a loja pode comprar mais cerveja e whisky de forma a aumentar o stock de bebida disponível na loja. Esta funcionalidade deve ser representado pelos métodos: compracerveja e comprawhisky, que irão aumentar a quantidade de bebida disponível na loja. Ambos os métodos recebem como argumento o número de litros de bebida a adicionar ao stock de loja. Programação com Objectos / Processamento de Dados I 46
EXERCÍCIO: Funcionalidade da garrafa de cerveja Uma garrafa de cerveja tem uma dada quantidade de cerveja. É possível saber se está cheia (através do valor booleano retornado pelo método estacheia) ou vazia (através do valor booleano retornado pelo método estavazia) e qual a quantidade bebida ainda presente na garrafa (através do método quantgarrafa). Tem ainda a funcionalidade de se poder beber uma dada quantidade da garrafa (representado pelo método bebecerveja). Se se pretender uma quantidade maior que a presente na garrafa, este método deve devolver false e deixar a garrafa com a quantidade inalterada. Se a quantidade presente na garrafa for maior ou igual à que se quer beber então este método deve devolver true. Programação com Objectos / Processamento de Dados I 47
EXERCÍCIO: Funcionalidade da garrafa de whisky Uma garrafa de whisky tem uma dada quantidade de whisky. É possível saber se está cheia (através do valor booleano retornado pelo método estacheia) ou vazia (através do valor booleano retornado pelo método estavazia) e qual a quantidade bebida ainda presente na garrafa (através do método quantgarrafa). Tem ainda a funcionalidade de se poder beber, de cada vez, 15 cl da garrafa (representado pelo método bebewhisky). Se se pretender uma quantidade maior que a presente na garrafa, este método deve devolver false e deixar a garrafa com a quantidade inalterada. Se a quantidade presente na garrafa for maior ou igual à que se quer beber então este método deve devolver true. Programação com Objectos / Processamento de Dados I 48
EXERCÍCIO: Outras funcionalidades Para a classe Loja deverá implementar o método equals que deverá comparar duas lojas. Considere que as lojas serão iguais se tiverem o mesmo nome. Para uma garrafa deve ser implementado o método tostring que deverá devolver a seguinte String: Garrafa de <tipo_de_bebida> ainda com <quantidade_de_bebida_disponível> Programação com Objectos / Processamento de Dados I 49
EXERCÍCIO: Objectivos Especifique em UML o diagrama de classes referente à situação descrita acima. Implemente, em Java, as classes participantes do sistema declarando os seus atributos e os métodos necessários para o seu correcto funcionamento. Implemente a classe Java de execução DemoLojas que execute os seguintes passos: Crie uma loja com o nome "Bar Académico" e com uma quantidade inicial de 5L de cerveja e 3L de whisky. Vende 4 garrafas de cerveja de 1L, 2 de 33 cl e uma de 25 cl. Invoque o método tostring sobre cada uma destas garrafas. Beba 33cl de todas as garrafas criadas. Invoque novamente o método tostring sobre cada uma destas garrafas. Vende mais uma garrafa de cerveja de 25cl. Vende 4 garrafas de whisky. Invoque o método tostring sobre cada uma destas garrafas. Bebe uma vez das primeiras três garrafas de whisky e duas vezes da quarta garrafa. Invoque novamente o método tostring sobre cada uma destas garrafas. Vende mais uma garrafa de whisky. Compre 5L de whisky. Vende mais uma garrafa de cerveja de 25cl. Vende mais uma garrafa de whisky. Programação com Objectos / Processamento de Dados I 50