Java - Herencia de clases y paso de parámetros

 
Vista:
sin imagen de perfil

Herencia de clases y paso de parámetros

Publicado por Ricardo (3 intervenciones) el 10/11/2022 21:27:12
Buenas tardes amigos,

Tengo un problema con un proyecto en Netbeans,
Es mi tercer módulo mensual en sistemas y me dejaron un trabajo en Netbeans, ya llevo varios intentos y no consigo que me quede, le moví tanto al código que termine por hacer una masa de códigos que no llevan ningún lado y termine por borrarlo,

Les comento un poco del trabajo:

Problema:

El banco MexBank quiere mejorar la eficiencia del código de su sistema. Se tienen 3 tipos de

cuentas: Tarjetas de Crédito, Tarjetas de Débito y Cuenta de Ahorro. El objetivo es crear una Clase
Cuenta base, de la cual, las demás Clases hereden sus propiedades y métodos.

Requerimientos:
• Proyecto debe de contener:herencia,métodos,uso de variables,uso de modificadores de
acceso, paso de variables, encapsulamiento y retorno de valores.
Consideraciones:
• La tarjeta de crédito tiene saldo negativo.
• El método de sumarInterés aumenta el 15% del monto actual a la deuda.
• El método invertir aumenta el 10% al monto actual.
• El método retirar resta la cantidad indicada al monto actual.

Adjunto imagen de las 3 clases hijas,

De antemano les agradezco mucho su atención y tiempo aunque sea solo para leerme,
Les deseo un excelente día.
Screenshot_2022-11-10-14-15-55-090-edit_com.google.android.apps.docs
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

Herencia de clases y paso de parámetros

Publicado por Kabuto (1381 intervenciones) el 11/11/2022 20:03:45
Hola Ricardo

Veamos, la CuentaBase podría ser esta.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class CuentaBase {
 
	protected double montoActual;
 
	public CuentaBase(double apertura) {
		montoActual = apertura;
	}
 
	public double getSaldo() {
		return montoActual;
	}
 
	public void depositar(double cantidad) {
		montoActual += cantidad;
	}
 
}
Un atributo saldo con modificador protected para que sus clases hijas (y solo ellas) puedan acceder directamente a él.
Un método getter y un método para depositar cantidades
Todo esto será común a las tres clases hijas herederas.

Si se quiere, se pueden añadir más atributos como nombre y apellido del titular, teléfono, email,..... pero de momento tenemos lo básico.

Las clases hijas.
Comenzamos por TarjetaDebito.
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TarjetaDebito extends CuentaBase {
 
	public TarjetaDebito(double apertura) {
		super(apertura);
	}
 
	public void retirar(double cantidad) {
		if (cantidad > montoActual)
			System.out.println("No hay suficiente saldo para cubrir la retirada");
		else
			montoActual -= cantidad;
	}
}
Su constructor recibe el importe de apertura inicial y lo transfiere a su clase "madre" con el método super().

Tiene un método retirar() que recibe una cantidad y hay que restarla del monto actual, si es que hay suficiente saldo disponible.

Luego la clase TarjetaCredito.
Esta clase tiene la peculiaridad de que funciona con deuda, es decir, su monto siempre es negativo. Pero su clase madre está escrita para funcionar con un monto positivo y esto es lo que estamos heredando.

Podemos solucionarlo de forma sencilla respetando el funcionamiento heredado, lo único que haremos será sobre escribir el método getSaldo() para que al mostrar en pantalla el valor del monto, salga en negativo, aunque en realidad internamente sea un valor positivo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TarjetaCredito extends CuentaBase {
 
	public TarjetaCredito(double apertura) {
		super(apertura);
	}
 
	/*
	 * Puesto que esta cuenta funciona con saldo negativo,
	 * hay que sobreescribir el método heredado getSaldo()
	 * para que muestre el monto en negativo
	 */
 
	@Override
	public double getSaldo() {
		return montoActual * -1;
	}
 
	public void sumaInteres() {
		montoActual *= 1.15; //Deuda aumenta un 15%
	}
 
}
Además añade un nuevo método para sumar el interés de la deuda al monto actual.
Fíjate que en el diagrama del enunciado este método se supone que recibe una cantidad como argumento. Pero luego nos dicen que este método lo que tiene que hacer es sumar un 15% del monto actual para incrementar la deuda.
Entonces ¿de que nos va a servir recibir una cantidad?¿Qué quieren que hagamos con ella?

O yo no he entendido bien el enunciado, o este está mal expresado. Así que yo he optado por ignorar ese argumento, ya que a mi entender es innecesario.


Por último, la clase CuentaAhorro
1
2
3
4
5
6
7
8
9
10
public class CuentaAhorro extends CuentaBase {
 
	public CuentaAhorro(double apertura) {
		super(apertura);
	}
 
	public void invertir() {
		montoActual *= 1.10; //Se invierte un 10% del monto actual
	}
}
Añade un método llamado invertir() que amplia el monto actual en un 10%.
Aquí pasa lo mismo que con la clase anterior, el diagrama dice que recibe una cantidad como argumento pero luego al interpretar el enunciado no parece ser necesario.
Así que de nuevo, he decidido omitirlo.

Pues, teniendo ya todas las clases escritas, solo queda probarlas.
Podemos hacer una clase de prueba, donde testear los distintos métodos de cada clase y comprobar que funcionan como se espera.

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
28
29
30
31
32
33
34
public class Prueba {
 
	public static void main(String[] args) {
 
		System.out.println("\tProbando cuenta TarjetaDebito...");
		TarjetaDebito debito = new TarjetaDebito(100);
		System.out.println("Saldo inicial: " + debito.getSaldo());
		System.out.println("Intentando retirar una cantidad de 150...");
		debito.retirar(150);
		System.out.println("Aumentando saldo para poder cubrir la retirada...");
		debito.depositar(100);
		debito.retirar(150);
		System.out.println("Saldo final tras retirar: " + debito.getSaldo());
 
		System.out.println("\n\n\tProbando cuenta TarjetaCredito...");
		TarjetaCredito credito = new TarjetaCredito(300);
		System.out.println("Deuda inicial: " + credito.getSaldo());
		System.out.println("Aumentando deuda y aplicando intereses...");
		credito.depositar(200);
		credito.sumaInteres();
		System.out.println("Saldo final: " + credito.getSaldo());
 
		System.out.println("\n\n\tProbando CuentaAhorro...");
		CuentaAhorro ahorro = new CuentaAhorro(1000);
		System.out.println("Saldo inicial: " + ahorro.getSaldo());
		System.out.println("Aumentando la inversión...");
		ahorro.invertir();
		System.out.println("Saldo final: " + ahorro.getSaldo());
 
		System.out.println("\n\t\tFIN DE PROGRAMA");
 
	}
 
}

Y con esto diría que queda resuelto el ejercicio.

Si tienes más dudas o crees que algo no es correcto, coméntalo por aquí.

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
1
Comentar
sin imagen de perfil

Herencia de clases y paso de parámetros

Publicado por Ricardo (3 intervenciones) el 11/11/2022 20:22:00
Buen día Kabuto,

Te lo agradezco amigo, me sirve perfecto, ya solo agregue algunos datos extra para las cuentas pero me resolviste perfecto la duda donde me quedaba atorado y no sabía explicarlo o expresarlo, además aprendí mucho con tu ayuda y me sirvió para reforzar y pulir un segundo ejercicio que tenía.

Te lo agradezco mucho,
Te deseo un excelente día amigo.
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

Herencia de clases y paso de parámetros

Publicado por Kabuto (1381 intervenciones) el 11/11/2022 23:23:44
Me alegro.

Respecto a la clase TarjetaCredito y su "monto negativo".
También podríamos haberlo resuelto haciendo que realmente el valor de su atributo sea negativo.

Habría que multiplicar por -1 el valor de "apertura" para convertirlo en negativo y sobreescribir el método depositar para que en lugar de sumar cantidad al monto, las reste:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class TarjetaCredito extends CuentaBase {
 
	public TarjetaCredito(double apertura) {
		super(apertura * -1);
	}
 
	@Override
	public void depositar(double cantidad) {
		saldo -= cantidad;
	}
 
	public void sumaInteres() {
		montoActual *= 1.15; //Deuda aumenta un 15%
	}
 
}

Sería una solución válida, quizás incluso más ajustada a lo que establece el enunciado.
Pero opté por la otra solución, la de simplemente pasar a negativo el valor que retorna el método getSaldo(), por ser un poco más sencilla y ofrecer el mismo resultado.

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

Herencia de clases y paso de parámetros

Publicado por Ricardo (3 intervenciones) el 12/11/2022 08:10:10
Esa también es una buena forma y como dices un poco más apegada al enunciado, la pondré y probaré, aunque la primera también fue una excelente solución.
De verdad te lo agradezco amigo, creeme aprendí más en la lección que me diste que en lo que ví de material de apoyo, gracias amigo.

Saludos
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

Herencia de clases y paso de parámetros

Publicado por Patricia Prez (1 intervención) el 19/02/2023 23:02:24
Saludos!! Kabuto MIL GRACIAS!!

Fue de gran ayuda, tu ejemplo. Gracias nuevamente
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

Herencia de clases y paso de parámetros

Publicado por Antonio (1 intervención) el 05/08/2023 06:56:30
Hola que tal amigo que cosas extras le agregaste ??
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

Herencia de clases y paso de parámetros

Publicado por Oscar (2 intervenciones) el 19/03/2023 17:43:49
Hola Kabuto, buen dia.
Estoy realizando este mismo ejercicio, pero al atributo montoActual en la clase padre CuentaBase en lugar de ponerlo como protected lo quiero poner como private.
Ya genere los getters y setters pero al mometno de implementarlos en las clases hijas de TarjetaCredito, TarjetaDebito y CuentaAhorro no se como hacerlo y me marca error.
Saludos.
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

Herencia de clases y paso de parámetros

Publicado por Kabuto (1381 intervenciones) el 19/03/2023 23:21:08
Hola Oscar.

Usar protected en las superclase suele facilitar las cosas y simplificar el código que escribiremos en las clases hijas.

Pero, si queremos usar private, puede hacerse sin problema. Lo único que ahora en las clases hijas tendremos que valernos de métodos get y set.

Bien, modifiquemos la superclase estableciendo el atributo "montoActual" como private.
Y añadiremos un método set.
No es necesario otro método get, porque en realidad ya tenemos el método getSaldo() que ya se encarga de retornarnos el atributo "montoActual". Se le puede cambiar el nombre a getMonto() si lo preferís.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class CuentaBase {
 
	private double montoActual;
 
	public CuentaBase(double apertura) {
		montoActual = apertura;
	}
 
	public void setMonto(double monto) {
		montoActual = monto;
	}
 
	public double getSaldo() {
		return montoActual;
	}
 
	public void depositar(double cantidad) {
		montoActual += cantidad;
	}
 
}

Bien, tras este cambio, ahora las clases hijas nos van a dar error, ya que hemos restringido la visibilidad del atributo y ya no pueden actuar directamente sobre él.
1
2
3
4
5
6
7
8
9
10
public class CuentaAhorro extends CuentaBase {
 
	public CuentaAhorro(double apertura) {
		super(apertura);
	}
 
	public void invertir() {
		montoActual *= 1.10; //Se invierte un 10% del saldo actual
	}
}

Para corregirlo, debemos combinar los métodos setMonto() y getSaldo() para poder hacer la misma operación
1
2
3
4
5
6
7
8
9
10
public class CuentaAhorro extends CuentaBase {
 
	public CuentaAhorro(double apertura) {
		super(apertura);
	}
 
	public void invertir() {
		setMonto(getSaldo() * 1.10);//Se invierte un 10% del saldo actual
	}
}

Como veis, la corrección es sencilla en este caso.

Pero vamos a ver la clase TarjetaCredito.
Hay dos métodos a corregir:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TarjetaCredito extends CuentaBase {
 
	public TarjetaCredito(double apertura) {
		super(apertura);
	}
 
	/*
	 * Puesto que esta cuenta funciona con saldo negativo,
	 * hay que sobreescribir el método heredado getSaldo()
	 * para que muestre el monto en negativo
	 */
	@Override
	public double getSaldo() {
		return montoActual * -1;
	}
 
	public void sumaInteres() {
		montoActual *= 1.15; //Deuda aumenta un 15%
	}
}

El método sumaInteres() PARECE QUE ES fácil(luego explico por qué "parece fácil") de corregir, haríamos lo mismo que hemos hecho antes:
1
2
3
public void sumaInteres() {
		setMonto(getSaldo() * 1.15); //Deuda aumenta un 15%
	}

Pero, ¿Qué pasa con el método getSaldo()?
Este no es un método propio de la clase TarjetaCredito, es un método de la superclase que estamos sobre escribiendo(Override).

Entonces, aquí hay un problema. Cuando invocamos a este método por su nombre.. ¿a quién estamos llamando en realidad?
¿Al getSaldo() de la superclase o al getSaldo() que hemos sobre escrito?
Son métodos distintos, el getSaldo() que hemos sobre escrito retorna el saldo pero con valor negativo.

Como estamos dentro del ámbito de la clase TarjetaCredito, al invocar a getSaldo() estamos llamando al método sobre escrito. Esto significa que ahora el método sumaInteres() que PARECÍA FÁCIL de corregir, ahora resulta que está funcionando mal.
Porque nosotros queríamos acceder al "montoActual" de forma normal, pero resulta que lo estamos obteniendo con valor negativo porque el monto no nos lo está dando la superclase como pensábamos, nos lo está dando la propia clase hija, quién lo retorna con valor negativo.

Pero bueno, no es un gran problema, tiene fácil solución. En estos casos donde hay dos versiones distintas de un mismo método (el de la superclase y el de la clase hija), podemos usar la palabra reservada super para especificar cuál versión es la que deseamos
1
2
3
public void sumaInteres() {
		setMonto(super.getSaldo() * 1.15); //Deuda aumenta un 15%
	}

Y también hay que corregir el método getSaldo(), de la clase hija:
1
2
3
4
@Override
	public double getSaldo() {
		return super.getSaldo() * -1;
	}


Bien, solo falta una clase por corregir:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TarjetaDebito extends CuentaBase {
 
	public TarjetaDebito(double apertura) {
		super(apertura);
	}
 
	public void retirar(double cantidad) {
		if (cantidad > montoActual)
			System.out.println("No hay suficiente saldo para cubrir la retirada");
		else
			montoActual -= cantidad;
	}
}

No es mayor problema, ya hemos visto como hacerlo:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TarjetaDebito extends CuentaBase {
 
	public TarjetaDebito(double apertura) {
		super(apertura);
	}
 
	public void retirar(double cantidad) {
		if (cantidad > getSaldo())
			System.out.println("No hay suficiente saldo para cubrir la retirada");
		else
			setMonto(getSaldo() - cantidad);
	}
}

Y ya está.
Empleando los get y set, y teniendo cuidado a quien invocamos cuando estamos sobre escribiendo métodos, queda solucionado.

Pero como puede verse, todo es más fácil y cómodo si dejamos que las clases hijas puedan "ver" los atributos que heredan con el modificador protected. Después de todo, esos atributos también son suyos, no son exclusivos de la superclase.

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
1
Comentar
sin imagen de perfil

Herencia de clases y paso de parámetros

Publicado por Oscar Jose (2 intervenciones) el 20/03/2023 03:50:58
Muchas gracias amigo.
Creo no puede haber mejor explicación, me haz ayudado a entender de una mejor forma el uso de los getters y setters, al igual que el uso del private, eres un master amigo.
Nuevamente muchas gracias.
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