12. Tipos enumerados

Suponha que, num jogo, as jogadas que os jogadores fazem podem ter efeitos diferentes, em vez de resultarem sempre na adição dos pontos da jogada à pontuação geral do jogador. O efeito poderá ser, por exemplo, a adição, a subtração ou a multiplicação dos pontos da jogada à/da/pela pontuação do jogador. Poderá ser ainda a substituição da pontuação do jogador pelos pontos dessa jogada ou por zero.

Uma abordagem NÃO satisfatória para podermos controlar o tipo de efeito que as jogadas devem ter em cada execução do programa, passa por usar uma variável cujo valor represente o efeito desejado. Podemos optar por declarar uma variável efeito , por exemplo, e dar-lhe valores 1, 2, 3, 4 ou 5 para representar cada efeito (1: Adição, 2: Subtração, 3: Multiplicação, 4: Substituição, 5: Nulo). Ou podemos optar por declarar a variável com o tipo char e usar as iniciais dos nomes que demos aos efeitos – 'A', ‘S’, 'M', 'U' ou 'N' – para representar cada uma delas (com o inconveniente de ter que evitar letras repetidas).

Esta abordagem, em qualquer das suas formas, tem três inconvenientes:

  1. O programador tem que relembrar a relação que definiu entre efeitos e números (ou carateres) sempre que precisa de trabalhar com essa informação, de modo a que as coisas façam sentido;
  2. Sempre que usa um valor que não está no conjunto que definiu para os valores relevantes, o programa fica incorreto, embora o compilador não se “queixe”;
  3. O programa torna-se pouco legível.

 

A linguagem Java permite-nos trabalhar com estes tipos de informação duma forma muito mais segura e que promove a legibilidade dos programas.

Os enumerados no Java permitem-nos definir tipos de dados não primitivos em que

 

Definimos agora o enumerado EfeitoJogada criando um ficheiro de nome EfeitoJogada.java (tal como fazemos para as classes) onde definimos todos os valores possíveis para este tipo de dados não primitivo:

Repare na palavra reservada enum que é usada em substituição da palavra class.

À semelhança de qualquer outro tipo de dados podemos, por exemplo, declarar variáveis deste novo tipo:

Os benefícios que obtemos pelo facto de usarmos o enumerado EfeitoJogada são:

  1. O significado e valores das variáveis ficam fáceis de entender;
  2. Não podemos atribuir a estas variáveis valores que não estejam definidos no enumerado EfeitoJogada; se o fizermos, o compilador assinalará um erro.

Os valores de um enumerado (neste caso, desde ADICAO até NULO) são constantes, mas também são objetos pois são de um tipo não primitivo.

Cada valor do enumerado está associado a um número desde zero até ao número de elementos do enumerado – 1; esse número é o seu número de ordem (neste caso, os números de ordem de ADICAO e NULO são, respetivamente, 0 e 4).

Há vários métodos que são acessíveis a todos os enumerados:

A execução das instruções do seguinte método main:

Escreve as seguintes linhas no standard output:

Repare, nas últimas linhas, como os nomes dos efeitos aparecem pela mesma ordem com que foram definidos no enumerado.

Para classificarmos cada jogada com o respetivo efeito temos que alterar o método registarPontosJogada da classe Jogo e o método registarPontos da classe Jogador apresentados no capítulo anterior. É necessário adicionar um parâmetro do tipo EfeitoJogada a esses métodos para receber o efeito da jogada a registar. De acordo com o valor desse parâmetro, os pontos a registar vão ter o efeito correspondente ao sentido que demos a cada um dos valores do enumerado.

No método registarPontosJogada da classe Jogo a mudança no corpo do método é pequena: basta acrescentar o valor do efeito na invocação do método registarPontos sobre o jogador em questão.

No método registarPontos da classe Jogador, o valor do efeito define a mudança a aplicar à pontuação atual do jogador corrente – usámos uma instrução switch.

Em relação ao valor máximo numa só jogada, agora fazemos o cálculo da diferença entre a pontuação que o jogador tinha antes da jogada e a que tem após a jogada. É o valor dessa diferença que é comparado com o atual máximo numa só jogada.

O seguinte método main está de acordo com a nova versão do método registarPontosJogada da classe Jogo. Além de gerar aleatoriamente os valores para as pontuações das sucessivas jogadas, gera também o efeito que cada jogada vai ter.

Faz isso gerando, a cada jogada de cada jogador, um inteiro entre 0 e 4 (o array EfeitoJogada.values() tem 5 elementos) e usa o efeito que está nessa posição do array EfeitoJogada.values() como valor para o parâmetro na invocação do método registarPontosJogada.

O resultado de uma possível execução deste main:

 

Em capítulos mais à frente, quando falarmos em padrões de desenho, veremos que há formas melhores de abordar este assunto.

 


 

Anterior: 11.9. Representação UML

Seguinte: 13. Interfaces