Java - Llamada a objetos

 
Vista:
sin imagen de perfil

Llamada a objetos

Publicado por Yez (5 intervenciones) el 29/09/2022 22:59:55
Buenas.
El caso es que tengo la siguiente clase, como parte de un proyecto que estoy haciendo. No sé si pueden verla, pero en ella tengo un listado de objetos con sus respectivos atributos. Tengo constructores, getters y setters, pero cuando llamo al getNombre() de heroe1, por ejemplo, o de bestia1, me devuelve el nombre del último objeto de la lista, independientemente de si es Heroe o Bestia. A que puede deberse?
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Llamada a objetos

Publicado por Kabuto (1381 intervenciones) el 30/09/2022 01:24:07
Hola.

Sería necesario poder ver el resto de clases: Heroe, Bestia, Elfo, etc... a ver si es en ellas donde pueda radicar el problema.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Llamada a objetos

Publicado por Yez (5 intervenciones) el 30/09/2022 02:19:17
Hola.
Aquí están el resto de las clases.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Llamada a objetos

Publicado por Kabuto (1381 intervenciones) el 30/09/2022 12:24:04
Ok. Lo primero.

Una REGLA DE ORO en programación es no usar nunca la ñ, ni ningún otro carácter que sea ajeno al alfabeto inglés.
¿Por qué?
Porque esos caracteres NO son comunes a todos los "juegos de caracteres"(charsets) que existen(los ISO, los UNICODE, los UTF....). Algunos charsets no los tienen.., otros si los tienen pero están identificados con distinta numeración...no hay un consenso para esos caracteres.

Los charsets que interpretan nuestros textos, varían según la región, varían según el sistema operativo, varían según cada programa, varían según cada ordenador.....

¿Y que implica?
Pues que al compartir nuestros programas con otros programadores, o bien intentar editarlos en ordenadores que no son el nuestro, pasa esto:
imagen-2022-09-30-111402951

Las ñ no están siendo reconocidas en mi sistema, ni tampoco las palabras con tilde (aunque como están en los comentarios, no importa)

Ya no es solo un inconveniente de edición, si no que directamente nuestros programas pueden funcionar mal al intentar ejecutarlos en otros sistemas.

Por eso es importante evitar codificar usando estos caractes.
En lugar de getDaño(), puedes poner getDanio(), getDanyo(), getDanho(), ... o incluso si no quedase otra, pues en inglés getDamage()

Lo que sea con tal de evitar esos caracteres.


Dicho esto, y ya volviendo a tu problema con los nombres.
Esto se debe a que estás declarando los atributos y métodos de las clases como static.

Deberías buscar información para comprender mejor la diferencia entre declarar los elementos de una clase como static y como "no static".
No voy a explayarme aquí ahora con explicaciones más extensas, pero resumiendo..., cuando un atributo, o un método, se declara como static, este atributo va a pertenecer a la clase, y no a los objetos que vayamos a crear a partir de esta clase.

Es decir, veamos unos ejemplos en pseudocódigo:

1
2
clase Orco.
static String nombre;

Tenemos una clase Orco, con un atributo nombre declarado como static

Si yo ahora creo objetos Orco y les doy nombres:
1
2
3
4
5
6
Orco orco1 = nuevo Orco();
orco1.setNombre("Ugluk");
Orco orco2 = nuevo Orco();
orco2.setNombre("Gothmog");
Orco orco3 = nuevo Orco();
orco3.setNombre("Harg")

Yo puedo pensar que a cada Orco le he dado un nombre distinto, pero no es así.
Porque el atributo "nombre", al ser static, no pertenece a los objetos orco1, orco2 u orco3. Estos objetos, únicos e individuales, en realidad no tienen un atributo "nombre" único e individual.

Ese atributo "nombre" pertenece a la clase, no a los objetos. Así que todos los objetos van a compartir el mismo "nombre". Por eso, todos esos Orcos se van a llamar "Harg", porque es el último nombre que seteado.

Esto mismo te ocurre a ti, pero peor... Todos tus personajes, tanto Heroes como Bestias, comparten el mismo nombre.
Y esto es porque la clase madre Personaje tiene sus atributos como static
1
2
3
4
5
6
7
public abstract class Personaje {
 
	//Usualmente es mas seguro establecer variables privadas.
	private static String nombre;
	private static int puntosVida;
    private static int armadura;
    private static String raza;

Así que en realidad, no solo comparten "nombre". Todos tus Personajes van a compartir nombre, puntos de vida, armadura y raza.
Cuando un Personaje reciba daño, lo van a recibir todos. Porque los "puntos de vida" son compartidos por todos los personajes, nadie tiene su propia y única "barra de vida"

Para que todos estos atributos sean únicos e individuales para cada objeto perteneciente a esta clase, hay que quitar el modificador static.
Tanto de los atributos, como de los métodos.
Y hay que hacerlo en TODAS las clases que has escrito.

Fíjate que en algunos métodos, por el lío que se ha montado con lo de usar static, has tenido que anteponer el nombre de la clase para acceder a los atributos:
1
2
3
public static void setArmadura(int armadura) {
    Personaje.armadura = armadura;
}
Esto es un ejemplo muy gráfico del problema. El atributo "armadura", si lo declaras static, entones no pertenece a ESTE(this) personaje en concreto, si no que pertenece a la clase Personaje en general.
Y además esto te obliga a declarar también el método como static.

Pero, si le quitas al atributo armadura el modificador static, ahora este atributo sí pertenece a ESTE(this) personaje en concreto. Ya es suyo y propio, no es un valor compartido con el resto de personajes del juego.
Y además, el método ya no necesita ser static.
1
2
3
public void setArmadura(int armadura) {
		this.armadura = armadura;
	}


Cuando corrijas esto en la clase Personaje, te van a surgir otros problemas derivados de haber usado static desde el principio (es como un efecto dominó) y también de no haber usado una lógica correcta.

El método ataque() tiene un error de lógica.
No está recibiendo ningún argumento entre paréntesis. Es decir, un personaje ataca, vale, pero ¿a quién está atacando?
El método no sabe a quién tiene que atacar, no sabe quién va a recibir daño, no sabe de quién ha de tener en cuenta su nivel de armadura...

Esta carencia, la has "solucionado" llamando a los atributos de la clase que hasta ahora eran static.
Quizás haya sido este error de lógica, lo que te llevó a declarar los atributos y métodos como static, para poder acceder a los métodos de getArmadura() y getDanyo() que no podías acceder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Orco extends Bestia {
 
	public Orco(String nombre, int puntosVida, int armadura, String raza) {
		super(nombre, puntosVida, armadura, raza);
	}
 
	@Override
	public int ataque() {
		super.ataque();
		int porcentaje=Heroe.getArmadura() * 10 / 100;
		Heroe.setArmadura(getArmadura() - porcentaje);
		return Orco.getDanyo();
	}
 
}
Y no podías acceder, porque no estás usando la lógica correcta.

Ese método, ha de recibir como argumento un objeto Personaje, que representará el personaje que está siendo atacado, o sea, su rival.

Así que de nuevo en la clase Personaje, conviene modificar la declaración del método abstracto ataque() para que reciba un rival
1
2
3
	//Aqu� a�ad� los m�todos abtractos que voy a usar.
	public abstract int tirarDado();
	public abstract int ataque(Personaje rival);

Y ahora, en las clases que heredan directamente este método, es decir, Bestia y Humano cambiamos el código para que el ataque y los daños sea entre esos objetos en concreto.

Por ejemplo, en Bestia este método quedaría así (recuerda quitar todos los static)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Bestia extends Personaje {
 
	private int danyo;
 
    public int getDanyo() {
		return danyo;
	}
	public void setDanyo(int danyo) {
		this.danyo = danyo;
	}
	//Constructor heredado de Personaje.
	public Bestia(String nombre, int puntosVida, int armadura, String raza) {
		super(nombre, puntosVida, armadura, raza);
	}
    //M�todos heredados de Personaje.
	@Override
	public int tirarDado() {
		int tirada=(int) Math.floor(Math.random() * 91);
		return tirada;
	}
	@Override
	public int ataque(Personaje rival) {
		danyo = tirarDado() - rival.getArmadura();
		return danyo;
	}
 
}

Aquí en Bestia, simplemente calculamos el daño según armadura del rival y lo retornamos.
Para aplicar ese daño al rival, es decir, para restarle puntos de vida, lo hacemos en las clases hijas que heredan de Bestia.
Por ejemplo, la clase Orco:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Orco extends Bestia {
 
	public Orco(String nombre, int puntosVida, int armadura, String raza) {
		super(nombre, puntosVida, armadura, raza);
	}
 
	@Override
	public int ataque(Personaje rival) {
		//La clase madre Bestia nos calcula el danyo generado al rival
		int danyo = super.ataque(rival);
		//Ahora aplicamos ese danyo a la vida del rival
		rival.setPuntosVida(rival.getPuntosVida() - danyo);
		//Retornamos los puntos de danyo para poder mostrar en pantalla como informacion
		return danyo;
	}
 
}


Esto mismo habrá que hacerlo en la clase Trasgo.

Y repetimos también este mismo proceso para Heroe y sus hijas: Hobbit, Elfo y Humano
Es decir, Heroe calcula el daño y las clases hijas lo aplican a sus rivales.

No tengo tiempo para revisar nada más....

Aplica estos cambios, a ver si vas viendo más claro la lógica a seguir.
Comenta aquí tus progresos y seguimos ayudando con los siguientes pasos.

Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Llamada a objetos

Publicado por Yez (5 intervenciones) el 01/10/2022 03:20:53
Bien, de momento puedo decir que me ha salvado la vida. No sabía eso de los modificadores static, aunque mi profesor me dijo algo parecido y no lo entendí. Ahora al menos me cambia los nombres. Le agradezco muchísimo su respuesta tan detallada.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar