Ganhavel
Se for do nosso interesse ter programas
e, nesses programas,
então devemos
criar um interface Java, definindo essas capacidades comuns que nos interessam,
fazer com que as classes dos objetos que vamos usar implementem esse interface,
O seguinte interface define um tipo de dados – Ganhavel
– que engloba um conjunto de capacidades que um objeto pode ter:
xxxxxxxxxx
/**
* Este interface define um tipo de dados representando uma atividade que tem
* participantes com diferentes pontuacoes. Uma vez a atividade terminada,
* podem ser conhecido(s) o(s) vencedor(es)
*/
public interface Ganhavel {
/**
* A designacao deste ganhavel.
*/
String designacao();
/**
* Os nomes dos vencedor(es) deste ganhavel
* @return Os nomes dos participantes deste ganhavel que venceram
* @requires this.terminou()
*/
String [] vencedores();
/**
* Este ganhavel jah terminou?
*/
boolean terminou ();
/**
* Existe um participante com um dado nome neste ganhavel?
* @param nome O nome do participante.
* @return true se existe um participante com este nome neste ganhavel
* false cc
*/
boolean estahEmJogo (String nome);
/**
* A pontuacao de um dado participante deste ganhavel
* @param nome O nome do participante.
* @requires this.estahEmJogo(nome)
* @return A pontuacao do participante com este nome
*/
int pontuacao (String nome);
}
Repare que a nossa classe Jogo
da secção 11.8 já implementa todos estes métodos. No entanto, como Jogo
não implementa Ganhavel
, não seria possível usar um objeto do tipo Jogo
para instanciar um parâmetro do tipo Ganhavel
, nem atribuir a sua referência a uma variável do tipo Ganhavel
.
Suponha que numa qualquer classe cliente de Ganhavel
, definimos o método imprimeInformacaoParticipante
abaixo listado, com um parâmetro do tipo Ganhavel
e uma String
, que invoca uma série de métodos sobre o objeto Ganhavel
imprimindo a informação resultante no standard output.
xxxxxxxxxx
/**
* Imprime informacoes varias no standard ouput acerca de um ganhavel e de um
* participante
* @param g O ganhavel
* @param nome O (presumido) participante
* @requires g != null && nome != null
*/
static void imprimeInformacaoParticipante(Ganhavel g, String nome) {
StringBuilder informacao = new StringBuilder();
informacao.append("*** Informacao sobre " + g.designacao() + " e " +
nome + " ***\n");
if(g.estahEmJogo(nome)) {
informacao.append(nome + " participa\n");
if (g.terminou()) {
informacao.append(g.designacao() + " jah terminou\n");
String[] venceram = g.vencedores();
int indiceNome = indice(venceram, nome);
informacao.append(nome + (indiceNome == -1 ? " nao " : " "));
informacao.append(" venceu e teve " + g.pontuacao(nome) + " pontos\n");
} else {
informacao.append(g.designacao() + " ainda nao terminou.\n");
informacao.append(nome + " teve " + g.pontuacao(nome) + " pontos\n");
}
}
else {
informacao.append(nome + " nao participa\n");
}
System.out.println(informacao.toString());
}
/**
* Indice de um elemento num array
* @param colecao O array
* @param nome O valor a procurar
* @return O indice do elemento no array, se existir; -1 caso contrario
*/
static int indice(String[] colecao, String nome) {
for(int i = 0 ; i < colecao.length ; i++) {
if (colecao[i].equals(nome)) {
return i;
}
}
return -1;
}
Para podermos usar um objeto do tipo Jogo
como valor para o parâmetro g
do tipo Ganhavel
, teremos que declarar, na classe Jogo
, que esta implementa o interface Ganhavel
:
xxxxxxxxxx
/**
* Classe cujos objetos representam jogos
* @author Isabel Nunes
*/
public class Jogo implements Ganhavel {
... //atributos e metodos tal como definidos na seccao 11.8
}
Vamos ainda supor que temos uma classe ConcursoPublico
que também implementa o interface Ganhavel
.
O seguinte programa trabalha com dois objetos – um do tipo Jogo
, outro do tipo ConcursoPublico
– que são também do tipo Ganhavel
e, como tal, podem ser usados na invocação do método imprimeInformacaoParticipante
para instanciar o seu primeiro parâmetro.
xxxxxxxxxx
public class ClienteDeGanhavel {
public static void main(String[] args) {
Jogo meuJogo = new Jogo("Tiro ao Arco", 25);
meuJogo.juntarJogador("Pedro");
meuJogo.juntarJogador("Rita");
meuJogo.registarPontosJogada("Pedro", 20);
meuJogo.registarPontosJogada("Rita", 30);
ConcursoPublico concurso = new ConcursoPublico("PR-1234");
// algumas invocacoes de metodos sobre concurso...
imprimeInformacaoParticipante(meuJogo, "Rui");
imprimeInformacaoParticipante(meuJogo, "Pedro");
imprimeInformacaoParticipante(meuJogo, "Rita");
imprimeInformacaoParticipante(concurso, "Rita");
}
/**
* Imprime informacoes varias no standard ouput acerca de um ganhavel e de um
* participante
* @param g O ganhavel
* @param nome O (presumido) participante
*/
static void imprimeInformacaoParticipante(Ganhavel g, String nome) {
StringBuilder informacao = new StringBuilder();
informacao.append("*** Informacao sobre " + g.designacao() + " e " +
nome + " ***\n");
if(g.estahEmJogo(nome)) {
informacao.append(nome + " participa\n");
if (g.terminou()) {
informacao.append(g.designacao() + " jah terminou\n");
String[] venceram = g.vencedores();
int indiceNome = indice(venceram, nome);
informacao.append(nome + (indiceNome == -1 ? " nao " : " "));
informacao.append(" venceu e teve " + g.pontuacao(nome) + " pontos\n");
} else {
informacao.append(g.designacao() + " ainda nao terminou.\n");
informacao.append(nome + " teve " + g.pontuacao(nome) + " pontos\n");
}
}
else {
informacao.append(nome + " nao participa\n");
}
System.out.println(informacao.toString());
}
/**
* Indice de um elemento num array
* @param colecao O array
* @param nome O valor a procurar
* @return O indice do elemento no array, se existir; -1 caso contrario
*/
static int indice(String[] colecao, String nome) {
for(int i = 0 ; i < colecao.length ; i++) {
if (colecao[i].equals(nome)) {
return i;
}
}
return -1;
}
}
Quando executado, este programa produz o seguinte output:
xxxxxxxxxx
*** Informacao sobre Tiro ao Arco e Rui ***
Rui nao participa
*** Informacao sobre Tiro ao Arco e Pedro ***
Pedro participa
Tiro ao Arco jah terminou
Pedro nao venceu e teve 20 pontos
*** Informacao sobre Tiro ao Arco e Rita ***
Rita participa
Tiro ao Arco jah terminou
Rita venceu e teve 30 pontos
*** Informacao sobre PR-1234 e Rita ***
Rita participa
PR-1234 ainda nao terminou.
Rita teve 23 pontos
Repare que, ao termos definido o parâmetro do método com tipo Ganhavel
em vez de Jogo
, obtivemos um método cuja utilização é mais abrangente, pois esse parâmetro pode ser instanciado por qualquer objeto cujo tipo real seja subtipo de Ganhavel
. Se o tipo do parâmetro fosse Jogo
, estaríamos a reduzir a aplicabilidade do método a objetos do tipo Jogo
.
Anterior: 13.3. Subtipos
Seguinte: 13.5. O interface genérico List