2012-02-09 24 views
5

Lo sé, lo sé, hay un montón de respuestas simples que cubren la mayoría de los casos sobre cómo evitar esto.Declarar una variable dentro de una instrucción `if` en Java que es un tipo diferente según el condicional

En mi caso, quiero utilizar la información de entrada del usuario para crear jugadores de CPU en un juego. Si el usuario elige el modo fácil, entonces quiero declarar y crear instancias de una instancia de la clase EasyPlayer. De lo contrario, quiero declarar y crear una instancia de una instancia de la clase HardPlayer. De cualquier manera, el nombre específico de la variable debe ser "cpu" y el resto del código opera en "cpu" indiscriminadamente. Es decir, todas las diferencias en cómo operan están integradas en sus diferentes clases, que subclasifican la clase CpuPlayer.

Así que aquí está el código:

// Set the opponent. 
if (difficulty == 0){ 
    EasyPlayer cpu = new EasyPlayer(num_rounds); 
} 
else{ 
    HardPlayer cpu = new HardPlayer(num_rounds); 
} 

Esto me da el error cada vez más molesto cannot find symbol. Por lo que puedo leer, todos dicen que no se pueden hacer declaraciones dentro de un condicional como este debido a problemas de alcance y la posibilidad de que nunca ocurra.

Si es así, ¿cuál es la forma correcta de declarar alternativamente una sola variable como una de dos clases diferentes según la entrada del usuario?

+1

+1 para darse cuenta de que la solución que tiene aquí es insuficiente y viene a SO para obtener ayuda. –

Respuesta

10
CpuPlayer cpu; 

if (difficulty == 0){ 
    cpu = new EasyPlayer(num_rounds); 
} 
else{ 
    cpu = new HardPlayer(num_rounds); 
} 
+0

Ah. Momento principal de golpear la cabeza. Gracias. – ely

0

Declare primero, y luego asígnelo.

// Set the opponent. 
CpuPlayer cpu = null; 
if (difficulty == 0){ 
    cpu = new EasyPlayer(num_rounds); 
} 
else{ 
    cpu = new HardPlayer(num_rounds); 
} 
if(cpu == null) throw new IllegalStateException(); 
+0

La asignación nula al principio parece innecesaria, ya que hay un ELSE al condicional IF. Siempre que HardPlayer herede de CpuPlayer, y HardPlayer no arroje ninguna excepción durante la construcción, parecería que la primera y la última línea del programa son innecesarias. ¿Me estoy perdiendo de algo? – eternaln00b

+0

@SiddharthaShankar Es un hábito: muchas veces terminará con errores de "esta variable no puede haber sido asignada". – corsiKa

+2

La asignación nula y la verificación subsiguiente no son solo innecesarias, son perjudiciales porque convierten una verificación en tiempo de compilación en una verificación en tiempo de ejecución. Sin la asignación inicial, cualquier intento de usar 'cpu' después de la cláusula' else' dará como resultado un error en tiempo de compilación a menos que a 'cpu' se le haya asignado un valor (en este caso, una de las dos' nuevas' instancias) en todos ramas de código. En otras palabras, si alguna vez hubo una rama de código que olvidó establecer el valor, el compilador le diría (en lugar de tener que lanzar una excepción de tiempo de ejecución). – yshavit

0
// Set the opponent. 
CpuPlayer cpu; 
if (difficulty == 0){ 
    cpu = new EasyPlayer(num_rounds); 
} else{ 
    cpu = new HardPlayer(num_rounds); 
} 
1
CpuPlayer cpu; 
// Set the opponent. 
if (difficulty == 0){ 
    cpu = new EasyPlayer(num_rounds); 
} else{ 
    cpu = new HardPlayer(num_rounds); 
} 
2

Si su intención es llamar a los métodos disponibles para la clase CpuPlayer, entonces tal vez un patrón de diseño es mejor utilizar el Strategy Pattern. En su caso, es probable que añadir una nueva clase llamada CpuStrategy, y modificar su constructor CpuPlayer a algo como:

public CpuPlayer(CpuStrategy strategy, int num_rounds) 

Esto hace que el resto de su código sea más fácil de leer y probablemente más fácil de mantener también. Esto es lo que el fragmento original de código se vería así:

CpuPlayer cpu = new CpuPlayer(new CpuStrategy(difficulty), num_rounds); 

Nos deshicimos del if/else ya que la clase CpuStrategy se encargará de la diferencia entre los niveles de dificultad. Esto también tiene sentido ya que puedes abstraer la noción de "niveles de dificultad" del contenido de tu programa, que supongo que es la parte del juego.

+0

Gracias por la sugerencia y los detalles adicionales. Esta es de hecho una buena idea de rediseño. – ely

0

Podría ajustar el diseño de su estructura de clase. Cree una clase principal llamada Nivel y amplíe dos clases secundarias llamadas EasyLevel y HardLevel.

class EasyLevel : public Level 
{ 

    //implementation specific to easy level 
} 

class HardLevel : public Level 
{ 
    //implementation specific to hard level 
} 

en su clase de jugador, agregue un modificar el constructor para tomar un parámetro de tipo Nivel.

class Player 
{ 
    Level level; 
    int rounds; 

    public: 
    Player (Level level, int num_rounds) 
    { 
     this.level = level; 
     this.rounds = num_rounds; 
    } 

    play() 
    { 
     // use level variable to invoke implementation specific to the set level, hard or easy. 
    } 
} 

Esto hará que la estructura de clase sea más extensible. Como ejemplo, si necesita agregar otro 'medio' de nivel en el futuro, solo necesita extenderse desde el nivel de clase padre.

Cuestiones relacionadas