Ayuda Java - Ejercicio simple - Código complicado.

Zinicox

Buenas tardes, aquí un FPero.

He resuelto por mi cuenta un examen tipo que nos han dejado como ejemplo, pero mi código me parece complicado para lo que es el enunciado.

El enunciado es este

spoiler

Y mi código es el siguiente

Main Class
Clase Jugadores
Clase Atacantes
Clase Defensores
Clase Porteros

La principal duda que tengo es cómo podría simplificar de alguna manera el enfoque, para que el código sea algo más sencillo teniendo en cuenta que es un examen, si es que es posible.

JuAn4k4

getValoracion debería ser un campo calculado.

Puedes hacer clase abstracta Player { Dorsal, Estadísticas } y que getValoracion sea calculado (no setter) reciba stats y te devuelve el int.

Al meter datos construyese el mapa(dorsal -> player)

Atacante/Defensor/Portero deberían solo tener la implementación de getValoracion, y Player usarla para mostrar la descripción.
Y no duplicas codigo.

Y luego: Abstraerse cosas que se duplican, tipo:
Pregunta + leer int.
readStat(...)

1 respuesta
Zinicox

#2 Pues apuntado todo para darle una vuelta, muchas gracias por la respuesta.

desu

Leyendo el enunciado:

Se deberán utilizar todas las ventajas de la herencia de clases.

Si no hay ninguna ventaja en la herencia de clases que hago? jeje

1 respuesta
JuAn4k4

#4 Como casi todo, tiene ventajas e inconvenientes.

1 respuesta
desu

#5 Dejo de tener ventajas en java 8 hace 6 años.

Utiliza enums para las acciones posibles del usuario, no uses espa;ol e ingles, busca en google Java naming guide porque los nombres los pones mal, la clase siempre empieza en mayuscula.

    enum Action {
        ADD_ATTACK,
        ADD_DEFENDER,
        ADD_GOALKEEPER,
        ADD_GOAL,
        ADD_PASS,
        ADD_RECOVER,
        ADD_SAVE,
        SHOW_DATA,
        EXIT
    }

En el main seria algo asi, fijate que tu condicion del while no tiene ningun sentido, cuando llegas a option == 0 ya sale del loop : - )

NUNCA inicialices variables globales que no vas a usar.
En tu caso nombre y dorsal tenian una scope ("global" a nivel de main) que no era necesario....

    public static void main(String[] args) {
        printHeaders();
        while (true) {
            printAvailableActions();
            var action = readActionInput();
            switch (action) {
                case ADD_ATTACK -> addAttack();
                case ADD_DEFENDER -> addDefender();
                case ADD_GOALKEEPER -> addGoalkeeper();
                case ADD_GOAL -> addGoal();
                case ADD_PASS -> addPass();
                case ADD_RECOVER -> addRecover();
                case ADD_SAVE -> addSave();
                case SHOW_DATA -> showData();
                case EXIT -> exit();
            }
        }
    }

Fijate como muevo nombre y dorsal a una scope local

private static void addAttack() {
        System.out.println("Introduce el nombre y el dorsal");
        sc.nextLine();
        var name = sc.nextLine();
        var number = sc.nextInt();
        team.add(new Attacker(
                name,
                number,
                0,
                0,
                0
        ));
    }

private static Cli.Action readActionInput() {
    return actions[sc.nextInt()];
}

private static void exit() {
    System.out.println("Closing application.");
    System.exit(0);
}
2 2 respuestas
Zinicox

#6 Gracias por la respuesta, queda claro así.

1 respuesta
JuAn4k4

#6 No si ya, pero si le pone en el examen que no tiene ventajas y que va a usar composición o lo que sea, dependiendo de lo amargado que este, te ponen un 0 y a pastar. A mi me ha pasado mucho en el instituto de mostrar un punto de vista diferente a las cosas y ponerme un 0 por no ser el suyo.

1
desu

#7 Ve dandole y con el tiempo se te quedaran estas cosas.

De ahi lo que haces mal y deberias recordad es el instance of. Siempre que hagas un intance of piensa que estas haciendo algo mal.

Cuando detectes que estas haciendo dentro de un metodo contabilizar() un x instance of Portero o x instance of Defensor, el patron para resolverlo consiste en darle la vuelta.

Tu haces, instance of X, castear a X, llamar metodo.

void contablilizar(Jugador jugador, int x) {
   if (jugador instance of Atacante) {
        ((Atacante) jugador).contabilizar(x)
   }
   if (jugador instanfe of Defensor) {
       ((Defensor) jugador).contabilizar(x)
  }
   if (jugador instanfe of Portero) {
      System.out.println("ERROR")
  }
{

Usas una interficie en su lugar, en tu caso la puedes meter en la clase abstracta que tenga el método contabillizar.

interface Contabilizar {
  contabiliza(int x);
}

abstract class Jugador implementa Contabilizar {

}

class Atacante extends Jugador{
  contabiliza(int x) {
    // todo
  }
}

class Defensor extends Jugador {
  contabiliza(int x) {
    // todo
  }
}

class Portero extends Jugador {
  contabiliza(int x) {
    System.out.println("NO EXISTE")
  }
}

Has dado la vuelta, a la dependencia, no necesitas castear porque cada clase sabe lo que tiene que hacer.
Ahora puedes usar jugador.contabiliza(x).
Como todos los jugadores implementan la interficie Contabilizar, cuando llamas el codigo automaticamente Java sabe quien es quien.

void contablilizar(Jugador jugador, int x) {
  jugador.contabiliza(x)
{

Nota, en tu caso al usar una clase abstracta no "haria falta" la interface, al ser un ejercicio de practica no tiene mucho sentido tampoco XD. Aqui tienes que pensar si tu profesor hacia 1 interface para cada metodo o lo metia todo en la clase abstracta sin interfaces. seguramente lo 2 XD

2 1 respuesta
Zinicox

#9 Pues la interface ni siquiera la habíamos mirado todavía, pero tal y como lo dices me queda mucho más claro. Gracias de nuevo.

Usuarios habituales

  • Zinicox
  • desu
  • JuAn4k4