Programação com Objectos/Teste de 2011/01/10

From Wiki**3

< Programação com Objectos

Parte 1 (resposta múltipla)

UML-teste-po-20110110.png
1.1. Considere o diagrama UML da figura 1 (à direita). Qual das seguintes afirmações está correcta?
  1. doThat pode ser invocado através de referências para I
  2. doThat não está definido para B
  3. doIt pode ser invocado através de referências para C
  4. A implementa I
  5. A é uma classe derivada de C

1.2. Que padrão de desenho permite especificar numa classe o esqueleto de um algoritmo, deixando para as subclasses a concretização dos seus passos?

  1. Strategy
  2. Bridge
  3. Template Method
  4. Visitor
  5. State

1.3. Em Java, qual das seguintes frases está correcta?

  1. todas as classes são derivadas de java.lang.Class
  2. uma classe interna não pode ser anónima
  3. uma classe anónima pode implementar uma interface
  4. java.lang.Object contém os métodos que permitem definir a ordem por omissão entre quaisquer objectos
  5. uma classe abstracta pode ser instanciada se definir construtores

1.4. Em Java, um construtor...

  1. não pode chamar outros construtores
  2. não pode chamar funções static
  3. chama sempre o construtor da superclasse
  4. não pode ser privado
  5. não pode declarar variáveis locais

1.5. Em Java, as classes internas...

  1. não podem ser serializáveis (i.e., não podem implementar java.io.Serializable)
  2. não podem conter métodos que lancem excepções
  3. podem ser instanciadas dentro de qualquer bloco de uma função
  4. constituem um mecanismo para uso exclusivo do tratamento de excepções
  5. não podem ter métodos públicos

1.6. Em Java, o método equals...

  1. não está disponível nas classes da package java.util
  2. é utilizado para definir ordem entre as instâncias de uma classe
  3. está disponível apenas para classes que implementem java.io.Serializable
  4. permite comparar apenas objectos com outros da mesma classe
  5. permite comparar dois objectos de qualquer tipo

1.7. Em Java, a interface java.lang.Comparable ...

  1. é implementada pela classe java.lang.Object
  2. as instâncias das suas implementações podem ser utilizadas como chaves pela classe java.util.TreeMap
  3. uma classe não deve implementá-la se quiser que as suas instâncias sejam serializáveis
  4. só é relevante para classes que implementem java.util.List
  5. as respostas anteriores estão erradas

1.8. Relativamente aos padrões de desenho State e Strategy...

  1. ambos especificam a delegação de acções em objectos usados pelo cliente
  2. as estratégias têm de ser fixadas na altura da criação do cliente, mas os estados não
  3. são idênticos, mas as classes que implementam as estratégias são em número fixo
  4. gerem as dependências de objectos das suas implementações
  5. tratam da mesma forma objectos individuais e suas agregações

1.9. O padrão de desenho Decorator...

  1. permite adicionar funcionalidade a um objecto sem alterar a sua interface
  2. não pode ser aplicado em conjunto com padrão Visitor
  3. permite ajustar a interface e o comportamento de um objecto
  4. permite aplicar uma operação a uma estrutura de objectos
  5. permite estabelecer o esqueleto de um algoritmo

1.10. O padrão de desenho Abstract Factory...

  1. representa a construção de uma colecção
  2. gerir as dependências de outros objectos relativamente ao estado de um objecto
  3. permite abstrair a criação de famílias de objectos para uma aplicação
  4. permite tratar famílias de objectos e seus grupos indiscriminadamente
  5. permite que o comportamento de um objecto mude quando o seu estado muda

Parte 2

2.1. (1.5 val.) Na linguagem Smalltalk, o método subclassResponsibility pode ser invocado por uma superclasse para indicar que a implementação de um determinado método é da responsabilidade de uma subclasse. Desse modo, se for usada uma subclasse que não implemente o método, o programa chama a versão da superclasse e recebe uma notificação da falta durante a execução. Qual é o mecanismo discutido acima e como é disponibilizado na linguagem Java? Diga quais são as suas vantagens relativas.

2.2. (1.5 val.) O mecanismo de herança potencia o desenvolvimento incremental e a reutilização de funcionalidade existente. No entanto, apesar destes aspectos positivos, apresenta algumas limitações. Descreva algumas das limitações do mecanismo de herança (pode particularizar para Java) e em que medida a utilização de arquitecturas como as previstas em alguns padrões de desenho as minimizam.

2.3. (1.5 val.) Descreva o padrão de desenho State e as vantagens da sua utilização. Explique em que medida o mecanismo de polimorfismo de inclusão é importante para a definição e funcionamento da arquitectura prevista pelo padrão. Dê um exemplo de utilização do padrão.

2.4. (1.5 val.) O padrão de desenho Visitor permite abstrair a aplicação de uma operação a uma estrutura de objectos. Diga qual é o princípio de funcionamento do padrão e que vantagens apresenta a sua utilização. Quais são os problemas introduzidos pela utilização do padrão? Dê um exemplo de aplicação.

2.5. Considere o seguinte programa em Java: <java5> public abstract class Shell {

 protected Ghost _ghost;
 protected Shell(Ghost ghost) { 
   _ghost = ghost;
   System.out.println(getClass().getName());
 }
 public abstract boolean isOperational();
 public abstract void powerOn();

}

public class Virtual extends Shell {

 public Virtual(Ghost ghost) { super(ghost); }
 public boolean isOperational() { return _ghost.isHappy(); }
 public void powerOn() { System.out.println("always on: nothing to do"); }

}

public class Physical extends Shell {

 private boolean _poweredOn = false;
 public Physical(Ghost ghost) { super(ghost); powerOn(); }
 public boolean isOperational() { return _poweredOn && _ghost.isHappy(); }
 public void powerOn() { _poweredOn = true; }

}

public class NotReadyException extends Exception {}

public class ShellTester {

 public void assertOperational(Shell shell) throws NotReadyException {
   if (!shell.isOperational()) {
     throw new NotReadyException();
   }
 }

}

public class Ghost {

 String _name;
 public Ghost(String name) { _name = name; }
 public boolean isHappy() { return true; /* ghosts are happy */ }

}

public class Application {

 public static void main(String args[]) {
   Shell kusanagi = new Virtual(new Ghost("草薙素子"));
   Shell batou = new Physical(new Ghost("バトー"));
   ShellTester tester = new ShellTester();
   try { tester.assertOperational(kusanagi); }
   catch (NotReadyException e) { System.out.println("Kusanagi not ready!"); }
   try { tester.assertOperational(batou); }
   catch (NotReadyException e) { System.out.println("Batou not ready!"); }
 }

} </java5>

2.5.1. (1.0 val.) Que resultado se obtém quando se executa o seguinte programa? (represente mudanças de linha com \n)

2.5.2. (0.5 val.) Que padrão de desenho é usado no programa?

2.5.3. (1.5 val.) Desenhe o diagrama de sequência UML correspondente à execução do programa, incluindo as etapas de criação dos objectos. O diagrama de sequência deve conter os nomes das mensagens trocadas (não é necessário representar os argumentos dessas mensagens nem as de retorno; não é necessário explicitar o construtor de Shell).

2.6. Considere o seguinte domínio:

Uma biblioteca possui livros, CDs, vídeos e jogos. Todas estas obras são identificadas por um número de série, uma data de aquisição e uma descrição de catálogo. Os livros, CDs e vídeos têm ainda a indicação de qual é o título e de quem é o autor. Os vídeos e os jogos têm indicação de qual é a idade mínima para empréstimo. A biblioteca mantém sobre os seus visitantes um registo, no qual inclui (sobre cada um) o nome, a data de nascimento, morada e número de telefone. Quando é realizado um novo registo, o novo utilizador fica sem acesso às obras com idade controlada se a idade for menor que um valor dado (à medida que o tempo passa e o utilizador envelhece, o acesso vai também evoluindo). São definidos três níveis de acesso: infantil (>0), juvenil (>12) e adulto (>18). No caso de utilizadores não adultos, a biblioteca associa ao menor um utilizador adulto, que é responsável pelas obras emprestadas (mantém um registo dedicado às obras emprestadas ao menor). A biblioteca guarda um registo dos empréstimos realizados (obra emprestada, utilizador e datas de empréstimo e limite para entrega). É possível pedir várias obras num único empréstimo e é possível contabilizar, tanto por utilizador, como na totalidade dos utilizadores, o número de obras emprestadas. Se uma obra não estiver disponível, é possível deixar um contacto para notificação em caso de devolução.

2.6.1. (2.0 val.) Desenhe o diagrama de classes UML correspondente ao domínio apresentado. Represente as classes (seus nomes, métodos e atributos). Indique também as relações de herança, associação e agregação.

2.6.2. (4.0 val.) Implemente em Java todas as classes, bem como os seus atributos e métodos, do domínio apresentado. Considere que deve haver flexibilidade na definição do tipo de cliente, na forma de transitar entre tipos de cliente, e no registo de empréstimos.

Chave da Parte 1

UML-teste-po-20110110.png
1.1. Considere o diagrama UML da figura 1 (à direita). Qual das seguintes afirmações está correcta?
  1. doThat pode ser invocado através de referências para I
  2. doThat não está definido para B
  3. doIt pode ser invocado através de referências para C
  4. A implementa I
  5. A é uma classe derivada de C

1.2. Que padrão de desenho permite especificar numa classe o esqueleto de um algoritmo, deixando para as subclasses a concretização dos seus passos?

  1. Strategy
  2. Bridge
  3. Template Method
  4. Visitor
  5. State

1.3. Em Java, qual das seguintes frases está correcta?

  1. todas as classes são derivadas de java.lang.Class
  2. uma classe interna não pode ser anónima
  3. uma classe anónima pode implementar uma interface
  4. java.lang.Object contém os métodos que permitem definir a ordem por omissão entre quaisquer objectos
  5. uma classe abstracta pode ser instanciada se definir construtores

1.4. Em Java, um construtor...

  1. não pode chamar outros construtores
  2. não pode chamar funções static
  3. chama sempre o construtor da superclasse
  4. não pode ser privado
  5. não pode declarar variáveis locais

1.5. Em Java, as classes internas...

  1. não podem ser serializáveis (i.e., não podem implementar java.io.Serializable)
  2. não podem conter métodos que lancem excepções
  3. podem ser instanciadas dentro de qualquer bloco de uma função
  4. constituem um mecanismo para uso exclusivo do tratamento de excepções
  5. não podem ter métodos públicos

1.6. Em Java, o método equals...

  1. não está disponível nas classes da package java.util
  2. é utilizado para definir ordem entre as instâncias de uma classe
  3. está disponível apenas para classes que implementem java.io.Serializable
  4. permite comparar apenas objectos com outros da mesma classe
  5. permite comparar dois objectos de qualquer tipo

1.7. Em Java, a interface java.lang.Comparable ...

  1. é implementada pela classe java.lang.Object
  2. as instâncias das suas implementações podem ser utilizadas como chaves pela classe java.util.TreeMap
  3. uma classe não deve implementá-la se quiser que as suas instâncias sejam serializáveis
  4. só é relevante para classes que implementem java.util.List
  5. as respostas anteriores estão erradas

1.8. Relativamente aos padrões de desenho State e Strategy...

  1. ambos especificam a delegação de acções em objectos usados pelo cliente
  2. as estratégias têm de ser fixadas na altura da criação do cliente, mas os estados não
  3. são idênticos, mas as classes que implementam as estratégias são em número fixo
  4. gerem as dependências de objectos das suas implementações
  5. tratam da mesma forma objectos individuais e suas agregações

1.9. O padrão de desenho Decorator...

  1. permite adicionar funcionalidade a um objecto sem alterar a sua interface
  2. não pode ser aplicado em conjunto com padrão Visitor
  3. permite ajustar a interface e o comportamento de um objecto
  4. permite aplicar uma operação a uma estrutura de objectos
  5. permite estabelecer o esqueleto de um algoritmo

1.10. O padrão de desenho Abstract Factory...

  1. representa a construção de uma colecção
  2. gerir as dependências de outros objectos relativamente ao estado de um objecto
  3. permite abstrair a criação de famílias de objectos para uma aplicação
  4. permite tratar famílias de objectos e seus grupos indiscriminadamente
  5. permite que o comportamento de um objecto mude quando o seu estado muda

Resolução da Parte 2

2.1. Smalltalk, subclassResponsibility, Abstracção

O mecanismo apresentado para Smalltalk corresponde ao processo de abstracção de um conceito e das suas operações: em particular, corresponde à abstracção de um método (o que invoca o método subclassResponsibility). A notificação, em tempo de execução, sobre a não implementação do método por uma subclasse (em Smalltalk), corresponde, em Java, a dois possíveis situações: o método é abstracto ou o método não é abstracto. A primeira situação corresponde à situação em que o método foi declarado com o qualificador abstract numa superclasse ou declarado numa interface e não foi redefinido numa subclasse. Nesta situação, o compilador avisa sobre o problema (em tempo de compilação). A segunda situação é semelhante à do Smalltalk e corresponde a apenas avisar, em tempo de execução, sobre a falta de um método (por exemplo, através do lançamento da excepção UnsupportedOperationException -- note-se, contudo, que a semântica associada à excepção é diferente da associada ao método subclassResponsibility).

2.2. Herança vs. Composição, Padrões

2.3. State

Aspectos importantes:

  • Descrição da estrutura e funcionamento do State
  • Vantagens: simplicidade de manutenção de uma máquina de estados associada ao cliente
  • State utiliza polimorfismo para permitir o intercâmbio de estados sem ser necessário alterar a aplicação cliente
  • Exemplo: Máquina de lavar (as classes previstas pelo State são os estados de funcionamento da máquina; os controlos da máquina correspondem a métodos do cliente e a delegações sobre os objectos que representam os vários estados).

2.4. Visitor

Aspectos importantes:

  • Descrição da estrutura e funcionamento do Visitor
  • Princípio de funcionamento (double dispatching): os objectos da estrutura de dados implementam um método (accept) que recebe qualquer visitante (polimorfismo); nesse método, é invocado sobre visitante o método que tem como argumento o objecto visitado (e que todos os visitantes têm de implementar).
  • Vantagens: é possível associar funcionalidade adicional a objectos sem necessidade de alterar as suas classes (a funcionalidade é específica para cada objecto visitado)
  • Desvantagens: devido ao número de métodos a implementar, pode não ser conveniente utilizar esta arquitectura, especialmente se não houver necessidade de ampliar a funcionalidade a associar aos objectos (o número total de métodos a manter é o produto do número de visitados pelo número de visitantes); a adição de um novo tipo de objecto ao conjunto dos visitados obriga à escrita de um novo método em todos os visitantes.
  • Exemplos: geração de código num compilador a partir de uma árvore sintáctica; desenho de uma cena a partir de uma descrição abstracta; cálculo de impostos sobre uma estrutura composta. Em geral, situações em que uma operação a realizar sobre uma estrutura de objectos e suas folhas possa ser generalizada.

2.5.1. Saída do programa

Vitual\nPhysical\n

2.5.2. Identificação do padrão de desenho utilizado

É possível identificar dois padrões: Adapter (entre Shell e Ghost) e Strategy (ShellTester).

2.5.3. Diagrama de sequência (UML)

Note-se que alguns objectos não indicam variáveis associadas (os resultados da criação desses objectos são imediatamente passados como argumentos de outros métodos).

PO-20110110-seq.png

2.6.1. Diagrama de classes (UML)

Esboço do diagrama de classes para o problema apresentado (algumas funções não foram apresentas; algumas classes, associadas a potenciais implementações do estado do utilizador não foram apresentadas).

PO-20110110-class.png

2.6.2. Exercício de programação

Usa-se o padrão State como forma de abstrair o comportamento dependente da idade do cliente.

<java5> // ... </java5>