No método registarPontosJogada
não basta fazer as duas tarefas que foram descritas; é necessário também registar os pontos no jogador a quem a jogada respeita. Ou seja, teríamos que ter também a instrução:
this.obterJogador(nomeJog).registarPontos(pontuacao); // errado
Mas temos um problema! O método obterJogador
, definido na classe Jogo
, é private
, ou seja, o compilador não aceitaria esta instrução na classe JogoNumeroExatoJogadas
.
A solução seria invocar o próprio método registarPontosJogada
implementado na classe Jogo
, que é public
, sobre o objeto corrente, obtendo algo como:
xxxxxxxxxx
public void registarPontosJogada (String nomeJog, int pontuacao) {
this.registarPontosJogada(nomeJog,pontuacao); // errado!!!
this.jogadasJahFeitas++;
if (this.jogadasJahFeitas == this.numeroJogadasAFazer) {
this.jahTerminou = true;
}
}
Mas não é isto que nós queremos! Desta forma estaríamos a invocar o próprio método registarPontosJogada
implementado na subclasse, – através de recursão –, obtendo, neste caso em particular, um processo que não termina.
O que nós queremos mesmo é executar o corpo do método registarPontosJogada
, tal como definido na superclasse, sobre o objeto corrente. A forma como indicamos isso ao compilador é usando a palavra super
em vez de this
, para referir o objeto corrente.
Na redefinição de um método
m
, numa classeB
, podemos invocar a versão dem
definida na superclasse deB
sobre o objeto corrente, referindo-nos a ele através da palavrasuper
.
Finalmente, a versão correta:
xxxxxxxxxx
@Override
public void registarPontosJogada (String nomeJog, int pontuacao) {
super.registarPontosJogada(nomeJog,pontuacao);
this.jogadasJahFeitas++;
if (this.jogadasJahFeitas == this.numeroJogadasAFazer) {
this.jahTerminou = true;
}
}
Repare que fizemos o mesmo na redefinição do método toString
. A representação textual de um objeto do tipo JogoNumeroExatoJogadas
inclui não só os valores dos novos atributos definidos nesta subclasse, mas também os valores dos atributos definidos na classe Jogo
.
A única maneira de conseguirmos aceder, a partir do método na subclasse, aos valores de todos os atributos definidos na superclasse, é através da invocação do método toString
tal como definido na classe Jogo
, acrescentando de seguida a informação adicionada pela subclasse.
xxxxxxxxxx
/**
* Representacao textual deste jogo.
*/
@Override
public String toString () {
StringBuilder sb = new StringBuilder();
sb.append(super.toString());
sb.append("Numero de jogadas a fazer: " + this.numeroJogadasAFazer + "\n");
sb.append("Numero de jogadas jah feitas: " + this.jogadasJahFeitas);
return sb.toString();
}
Vamos agora considerar este novo main
:
public static void main (String [] args) {
JogoNumeroExatoJogadas meuJogo = new JogoNumeroExatoJogadas("Spiral",4);
System.out.println("O numero de jogadas a fazer eh " + meuJogo.numeroJogadasAFazer());
meuJogo.juntarJogador("Maria");
meuJogo.juntarJogador("Pedro");
meuJogo.registarPontosJogada("Maria", 17);
meuJogo.registarPontosJogada("Pedro", 25);
meuJogo.registarPontosJogada("Maria", 17);
meuJogo.registarPontosJogada("Pedro", 9);
System.out.println("======================");
System.out.println(meuJogo.toString());
System.out.println("======================");
if(meuJogo.terminou()) {
System.out.println("Os vencedores sao:");
List<String> venceram = meuJogo.vencedores();
for (String jog : venceram) {
System.out.println(jog + " com " + meuJogo.pontuacao(jog));
}
} else {
System.out.println("Ainda nao terminou");
}
}
Ao executá-lo, iremos obter o seguinte output:
xxxxxxxxxx
O numero de jogadas a fazer eh 4
======================
Numero de jogadores: 2
Nome: Maria Pontuacao: 34 Maximo numa jogada: 17
Nome: Pedro Pontuacao: 34 Maximo numa jogada: 25
Numero de jogadas a fazer: 4
Numero de jogadas jah feitas: 4
======================
Os vencedores sao:
Pedro com 34
Como queremos que os vencedores deste novo tipo de jogo sejam calculados tal como na classe Jogo
, então não precisamos de redefinir o método vencedores
; pelo facto desta classe ser subclasse de Jogo
, o método vencedores
da classe Jogo
é herdado tal e qual como implementado nessa classe.
Anterior: 14.7. Outra subclasse de Jogo
Seguinte: 14.9. Redefinição versus atributos