[RESOLVIDO] Aplicativo Lançamento de uma moeda / Duvida: ENUM

Pessoal estou estudando java há alguns meses, sou novo no fórum e provavelmente devo participar mais, pois estou querendo aprender realmente. Estou com o livro da deitel 8° edição no cap.6 exercicio 6.29 que diz assim:

Escreva um aplicativo que simula o lançamento de uma moeda. deixe o proigrama lançar uma moeda toda vez que o usuário escolher a opção “Lançar Moeda” no menu. Conte o número de vezes que cada lado da moeda aparece. Exiba os resultados. O programa deve chamar um método “arremesso” separado que não aceita argumentos e retorna um valor a partir de um enum Moeda( Caras e Coroas ). [Nota: se o programa simular de maneira realista, o arremesso de moeda, cada lado da moeda deve aparecer aproximadamente metade das vezes.]

Vou postar meu código e os meus erros para vocês me ajudarem por favor. Não entendi muito bem sobre enum. Já pesquisei no google e só entendi que enum é uma classe e eu uso para declarar um tipo com um conjunto de CONSTANTES. Mais não sei como usa-las.

// Exercício 6.29: LancaMoeda.java
import java.util.Random;

public class LancaMoeda
{
	private enum Moeda{ Cara, Coroa };
	private int cara = 0; 
	private int coroa = 0;
	
	private Moeda cC; // variável do tipo MOEDA para armazenar CARA ou COROA
	
	Random lancar = new Random();
	
	public  Moeda arremesso()
	{
		int x = lancar.nextInt( 2 );	
		
		switch( x )
		{
			case 0:
				cC = Moeda.Cara;
				cara += 1;
				break;
			case 1:
			
				cC = Moeda.Coroa;
				coroa += 1;
				break;
		}
		
		return cC;	
	}
}
// Exercício 6.29: TestaLancaMoeda.java
// Lanca uma moeda toda vez que o usuário escolhe a opção Lançar Moeda
// Exibi o resultado e o número de vezes que lancei cara ou coroa
import java.util.Scanner;

public class TestaLancaMoeda
{
	public static void main( String[] args )
	{
		Scanner entrada = new Scanner( System.in );
		LancaMoeda   lancarMoeda = new LancaMoeda();
		
		System.out.println( "Escolha uma opção: \n\n1: Lançar Moeda.\n2: Sair.\n" );
		int x = entrada.nextInt();
		
		while( x == 1 ) // lança moedas até eu escolher Sair
		{
			Moeda.cc = lancarMoeda.arremesso();
			
			// exibi o arremesso, o número de caras lançadas até agora e o número coroas lançadas até agora
			System.out.printf( "%s\nNúmero de Caras lançadas: %d\nNúmero de Coroas lançadas: %d\n\n", 
				Moeda.cc, cara, coroa );
			
			// Pergunta novamente se quero sair ou lançar a moeda
			System.out.println( "Escolha uma opção: \n\n1: Lançar Moeda.\n2: Sair.\n" );
			x = entrada.nextInt();
		}	
	}
}

Uso o editor Geany. Muito bom na minha opinião.

São quatro erros que aparecem no aplicativo TestaLancaMoeda referente as variaveis cara, coroa e Moeda.cc;

            Moeda.cc = lancarMoeda.arremesso(); 

Isto é a declaração de uma variável cc? Se for, está com um “.” (ponto) a mais.

             System.out.printf( "%s\nNúmero de Caras lançadas: %d\nNúmero de Coroas lançadas: %d\n\n",   
                 Moeda.cc, cara, coroa );  

Quando você escreveu “private int cara;” na declaração da variável de instância “cara” da classe LancaMoeda, indicou que ela é “invisível” fora dessa classe LancaMoeda. Portanto, você não pode referenciar diretamente o valor de “cara” na classe TesteLancaMoeda.

A lógica do programa está perfeita. Falta aprender um pouco sobre controle de acesso, ou seja, como pegar um valor que está dentro de um objeto.

Eu realmente esqueci disso que quando declaro private na variavel é justamente para eu não utilzar na outra classe.

Eu removi o ponto e não mudou em nada na variável cc.

Poderia me explicar um pouco entçao sobre esse controle de acesso. Me embolei todo porque ainda não entendi muito bem esse lance de enum. Mais pelo visto você disse que a lógica está perfeita e o jvm não encontrou erro também nessa classe.

Fiz uma mudança e consegui executar o aplicativo corretamente sem nenhum erro.

Vou mostrar o código, mais ainda tenho dúvida, a mudança que eu fiz foi correta?

// Exercício 6.29: LancaMoeda.java
import java.util.Random;

public class LancaMoeda
{
	public static enum Moeda{ Cara, Coroa };
	public static int cara = 0; 
	public static int coroa = 0;

	private Moeda cC; // variável do tipo MOEDA para armazenar CARA ou COROA
	
	Random lancar = new Random();

	public  Moeda arremesso()
	{
		int x = lancar.nextInt( 2 );	

		switch( x )
		{
			case 0:
				cC = Moeda.Cara;
				cara += 1;
				break;

			case 1:
				cC = Moeda.Coroa;
				coroa += 1;
				break;
		}

		return cC;	
	}
}
// Exercício 6.29: TestaLancaMoeda.java
// Lanca uma moeda toda vez que o usuário escolhe a opção Lançar Moeda
// Exibi o resultado e o número de vezes que lancei cara ou coroa

import java.util.Scanner;

public class TestaLancaMoeda

{
	public static void main( String[] args )
	{
		Scanner entrada = new Scanner( System.in );
		LancaMoeda   lancarMoeda = new LancaMoeda();

		System.out.println( "Escolha uma opção: \n\n1: Lançar Moeda.\n2: Sair.\n" );
		int x = entrada.nextInt();

		while( x == 1 ) // lança moedas até eu escolher Sair
		{
			LancaMoeda.Moeda cc = lancarMoeda.arremesso();

			// exibi o arremesso, o número de caras lançadas até agora e o número coroas lançadas até agora
			System.out.printf( "%s\nNúmero de Caras lançadas: %d\nNúmero de Coroas lançadas: %d\n\n", 
				cc, LancaMoeda.cara, LancaMoeda.coroa );

			// Pergunta novamente se quero sair ou lançar a moeda
			System.out.println( "Escolha uma opção: \n\n1: Lançar Moeda.\n2: Sair.\n" );
			x = entrada.nextInt();
		}	
	}
}

As mudanças que eu fiz foi trocar as váriaveis:

PARA:

E chamar as variaveis pelo “NomeDaClasse.NomeDaVariavel” já que foram declaradas como static e public

Alguém poderia me responder por favor?

Lucas, NÃO SE DESESPERE !! Se alguém ainda não respondeu, é pq ou não sabe, ou ainda não viu ou se irritou com a sua pressa !

Tenha paciência !

Ficar dando Ups no post não vai ajudar em nada!.

:wink:

Ok. Não estou desesperado.

Seguinte. A mudança não foi boa, pois “quebra” um dos princípios da programação OO. O Encapsulamento.

O Encapsulamento define que se precisarmos mudar o valor de alguma variável de instância de um objeto, devemos enviar uma mensagem que recebe um valor como argumento e faz a alteração. Não podemos acessar variáveis de instância diretamente. Desta forma, os campos estarão escondidos para nós, o que previne alterações acidentais.

logo, o ideal é todo campo de uma classe ser private, e você disponibilizar um metodo para modificar esse atributo. Ou seja, um get e um set para tal.

Exemplo:

private int cara = 0; 

/* Metodo que dá acesso ao atributo privado para modificação */

public void setCara(int valor) {
    this.cara += valor;
}


/ * Metodo que dá acesso ao atributo privado para recuperação do valor * /
public int getCara(){
   return this.cara;
}

Como eu fui idiota…¬¬
Ja cansei de fazer exercícios usando métodos set e get e não lembrei de usar um get para recuperar os valores dos campos. ¬¬

Mais no caso como eu faço para recuperar a variavel Moeda cc que armazena o resultado da constante enum?

Do mesmo jeito que o sowyer sugeriu com os outros atributos:

public Moeda getMoeda() {
    return cC;
}

Ai é que está cara, isso eu ja entendi e já consegui retornar o valor dela

Eu não preciso de um metodo get porque eu ja tenho o metodo arremesso que retorna cC. Veja:

A minha dúvida restante, que acho que se perdeu um pouco. É a seguinte.

Na outra classe quando eu quero saber o valor de cC é só eu criar um objeto e chamar o metodo arremesso que ele retorna cC. Exemplo:

LancaMoeda   lancarMoeda = new LancaMoeda();  

lancarMoeda.arremesso();  // aqui eu consigo retornar o valor de cC

A minha dúvida é como eu faço para retornar esse valor de cC e armazenar em uma variavel na outra classe?
Porque se eu fizer assim :

String cC = lancarMoeda.arremesso();  // da errado;
Moeda cC = lancarMoeda.arremesso();  // da errado;
int cC = lancarMoeda.arremesso();  // da errado;

Então eu não consigo armazenar em uma variavel. Queria saber como eu faço isso. Lembrando que é em outra classe e que o retorno é um tipo enum Moeda que eu criei

Entendi. Bem, no código que você postou pela segunda vez já tem uma variável que pega o valor retornado: LancaMoeda.Moeda cc = lancarMoeda.arremesso(); .

Acho que você está fazendo confusão com o lance da Enum. Uma Enum é um objeto java normal. E como toda classe que você cria, ela é de um tipo específico, por isso você não pode atribuir a Moeda a uma String ou int.

Você criou a Enum DENTRO de outra classe, por isso esse código dá errado: Moeda cc = lancarMoeda.arremesso();. Como ela foi criada dentro da classe LancaMoeda, para declarar uma variável do tipo da Enum, você precisa colocar a classe externa seguida de “.” mais o tipo da Enum. Assim: LancaMoeda.Moeda variavelDoTipoEnum;.

Espero que tenha conseguido ajudar… qualquer coisa, grita aí =)

PO$#&#$$ finalmente consegui e entendi. Obrigado. Mas isso se aplica somente a constantes enum?

Não, isso se aplica a classes aninhadas também. Em Java você pode declarar uma classe dentro de outra. Exemplo:

public classe Externa {

    public class Interna {}

    public void metodoDaClasseExterna() {
        // Para criar objetos da classe interna dentro da externa continua igual.
        Interna objeto = new Interna();
    }

}

Para criar objetos da classe interna dentro de outra classe que não seja a externa fica:

public class OutraClasse {

    public void metodoDaOutraClasse() {
        // Primeiro cria-se um objeto da classe externa.
        Externa instanciaClasseExterna = new Externa();

        // Usa-se a instância da classe externa para criar a classe interna. Repare na declaração.
        Externa.Interna instanciaClasseInterna = instanciaClasseExterna.new Interna();
    }

}

Esse é um exemplo de classe aninhada, mas existem outros, como classe aninhada estática, classes anônimas e talz. Sugiro que leia o livro da Kate Sierra (Use a Cabeça - Java) que lá trata um pouco desse assunto, além de cobrir esses assuntos básicos de orientação a objeto. Também sugiro o livro preparatório para certificação SCJP, também da Kate, que trata com mais profundidade as regras envolvidas nisso, e também as Enums, que você estava confuso.

Bem, é isso… Boa sorte aí com Java e bons estudos… =)

Ainda não aprendi sobre classes aninhadas. Estudo pelo livro da deitel. Quando acabar provavelmente devo ler outros livros. Obrigado pela ajuda. Tópico Resolvido