Java - AYUDA con ejercicio POO

 
Vista:
Imágen de perfil de Lorena

AYUDA con ejercicio POO

Publicado por Lorena (1 intervención) el 05/03/2024 18:32:54
Buenas a todos!

A ver si hay algún alma caritativa que me pueda ayudar. Estoy en la segunda evaluación de 1ª de DAM, y nos han mandado un ejercicio con el siguiente enunciado (a mi parecer deja demasiado a la interpretación y no sé como enfocarlo). Sobre todo teniendo en cuenta que es solo para el usuario.

Desde que empezamos POO siempre hemos hecho gestores en los que manejábamos el alta por ejemplo de libros, modificaciones, ver listas, como mucho ventas...

Y en el enunciado nos piden incluir abstract, herencia, sobrecargas, polimorfismos...

Gracias de antemano!

Realiza un programa para la gestión de billetes para RENFE.

Dicha aplicación tendrá que poder reservar y pagar dicha reservas que haga un cliente, indicando el trayecto que va a hacer. Tenéis que crear la estructura de las clases necesarias para poder dar de alta trayectos y darlas de baja de un ArrayList. Dichos billetes pueden ser solo ida o ida y vuelta.

Será una aplicación que sólo utilizará el cliente.

Es imprescindible utilizar TODOS los principios básicos de la programación orientada a objetos.
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

AYUDA con ejercicio POO

Publicado por Kabuto (1383 intervenciones) el 11/03/2024 01:07:24
Veo tarde tu consulta, igualmente contesto por si aún puede ser útil.

Estos enunciados "vagos" en detalles los hacen a propósito para que le echemos imaginación por nuestra parte, en lugar de que tengamos que cumplir unos puntos precisos.

Sí, por un lado es más difícil, pero por otro lado nos dan libertad para resolverlo como mejor nos parezca. Así que podemos crear todas la clases que queramos con tal de cumplir el objetivo principal, que es aplicar POO a tope.

A ver, así a bote pronto, se me ocurre hacer una clase abstracta llamada Billete, la cuál tendrá dos hijas: BilleteIda y BilleteIdaVuelta
Ole, abstracción y herencia ya lo tenemos.

Todos los billetes tendrán en común un nº identificador, un cliente y un trayecto.
Cliente(id, nombre) y Trayecto(origen, destino, importe) también serán clases, que al ser atributos de Billete, ya estamos incluyendo también una relación de asociación entre clases.

A ver, vayamos creando las clases:
Cliente. Un id y un nombre, no hace falta complicarlo más.
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 Cliente {
 
	private String id;
	private String nombre;
 
	public Cliente(String id, String nombre) {
		this.id = id;
		this.nombre = nombre;
	}
 
	public String getId() {
		return id;
	}
 
	public void setId(String id) {
		this.id = id;
	}
 
	public String getNombre() {
		return nombre;
	}
 
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
 
}

Trayecto. Tiene un origen , un destino y un importe, o sea, el precio base de ese trayecto.
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
35
36
37
public class Trayecto {
 
	private String origen;
	private String destino;
	private double importe;
 
	public Trayecto(String origen, String destino, double importe) {
		this.origen = origen;
		this.destino = destino;
		this.importe = importe;
	}
 
	public String getOrigen() {
		return origen;
	}
 
	public void setOrigen(String origen) {
		this.origen = origen;
	}
 
	public String getDestino() {
		return destino;
	}
 
	public void setDestino(String destino) {
		this.destino = destino;
	}
 
	public double getImporte() {
		return importe;
	}
 
	public void setImporte(double importe) {
		this.importe = importe;
	}
 
}

La clase abstracta Billete.
Hemos dicho que tiene un identificador (se genera al azar) , un Cliente y un Trayecto.
También va a tener un método abstracto para calcular el importe final del billete. Este cálculo lo va a tener que hacer las clases hijas y será distinto para cada una.
Con esto ya tenemos sobreescritura de métodos.
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
35
36
37
38
39
40
41
42
43
import java.util.Random;
 
public abstract class Billete {
 
	protected final String idBillete;
	protected Cliente cliente;
	protected Trayecto trayecto;
 
	public Billete(Cliente cliente, Trayecto trayecto) {
		this.cliente = cliente;
		this.trayecto = trayecto;
		idBillete = generaID();
	}
 
	private String generaID() {
		Random azar = new Random();
		StringBuilder cadena = new StringBuilder();
		for (int i = 0; i < 9; i++)
			cadena.append(Integer.toString(azar.nextInt(10)));
 
		return cadena.toString();
	}
 
	public String getIdBillete() {
		return idBillete;
	}
 
	public Cliente getCliente() {
		return cliente;
	}
	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}
	public Trayecto getTrayecto() {
		return trayecto;
	}
	public void setTrayecto(Trayecto trayecto) {
		this.trayecto = trayecto;
	}
 
	public abstract double calcularPrecioFinal();
 
}

La clase BilleteIda.
No varía apenas respecto a su clase madre.
Simplemente hace el cálculo del precio final añadiéndole el IVA al importe del Trayecto.
Y sobreescribe el método toString() para poder presentar los datos en pantalla.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class BilleteIda extends Billete {
 
	public BilleteIda(Cliente cliente, Trayecto trayecto) {
		super(cliente, trayecto);
	}
 
	@Override
	public double calcularPrecioFinal() {
		//El precio del billete de ida es el importe del trayecto + 21% de IVA
		double importe = trayecto.getImporte();
		return importe + (importe * 21 / 100);
	}
 
	@Override
	public String toString() {
		return String.format("Billete Nº:%s\nCliente: %s\nTrayecto: %s--%s\nPrecio: %.2f", idBillete,
				cliente.getNombre(), trayecto.getOrigen(), trayecto.getDestino(), calcularPrecioFinal());
	}
 
}

La clase BilleteIdaVuelta.
Aquí se diferencia en que aporta un nuevo atributo: otro Trayecto, el de "vuelta", que es una copia del trayecto de "ida" pero invirtiendo el origen y el destino.
Además, al calcular el precio, se suman los importes de los dos trayectos, pero el de "vuelta" es un 50% más barato(este importe se reduce en el constructor de la clase).
El método toString() también es ligeramente distinto al de su clase hermana al mostrar las ciudades que componen el trayecto.
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
public class BilleteIdaVuelta extends Billete {
 
	private Trayecto vuelta;
 
	public BilleteIdaVuelta(Cliente cliente, Trayecto trayecto) {
		super(cliente, trayecto);
		//El trayecto de vuelta es como el trayecto de ida, pero invertido.
		//El importe es la mitad del importe de ida
		vuelta = new Trayecto(trayecto.getDestino(), trayecto.getOrigen(), trayecto.getImporte()/2);
	}
 
	@Override
	public double calcularPrecioFinal() {
		//El precio del billete ida y vuelta, es la suma de importes de los dos trayectos + 21% de IVA
		double importe = super.getTrayecto().getImporte() + vuelta.getImporte();
		return importe + (importe * 21 / 100);
	}
 
	@Override
	public String toString() {
		return String.format("Billete Nº:%s\nCliente: %s\nTrayecto: %s--%s--%s\nPrecio: %.2f", idBillete,
				cliente.getNombre(), trayecto.getOrigen(), trayecto.getDestino(), vuelta.getDestino(),
				calcularPrecioFinal());
	}
}

Pues con esto, ya podemos crear una clase main para poner en marcha un menú de alta y baja de billetes.

En mi caso, he decidido poner dos ArrayList.
Uno es para los billetes que los usuarios dan de alta y baja.
El otro, es un lista de objetos Trayecto , para así tener unos precios predefinidos. Esto no es realmente necesario.
Lo bueno es que los precios no los decide el usuario y así son valores con sentido, porque varían según la distancia del origen y destino.
Lo malo es que ahora el usuario ha de especificar correctamente los nombres del origen y del destino y de hecho en mi lista solo hay una combinación de cuatro ciudades concretas.
Pero bueno, al fin y al cabo, la intención del ejercicio es practicar POO, así que estos detalles "funcionales" no son lo que realmente importa.

Para dar de ALTA un billete, se piden los datos del cliente, el nombre del origen y el del destino. Si los datos son correctos se crea un billete y queda registrado.
Durante este proceso de ALTA habrá polimorfismo, ya que declaramos un elemento de la clase Billete, pero lo que vamos a referenciar en ese elemento será un BilleteIda o un BilleteIdaVuelta, según elija el usuario.

Para dar de BAJA, se pide el identificador del cliente. Con este dato, se buscan y muestran los números de billetes que hay asociados a dicho cliente, y este elige cuál de esos quiere dar de baja.
Y ya está, no se necesita hacer nada más complicado.
Clase VentaBilletes
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import java.util.ArrayList;
import java.util.Scanner;
 
public class VentaBilletes {
 
	private static final ArrayList<Trayecto> LISTA_TRAYECTOS = crearListadeTrayectos();
	private static ArrayList<Billete> billetes = new ArrayList<Billete>();
	private static Scanner teclado = new Scanner(System.in);
 
	public static void main(String[] args) {
 
		int opcion = 0;
		do {
			System.out.println("\n\n\t\tBILLETES RENFE");
			System.out.println("\t\t-------- -----\n");
			System.out.println("[1] -- ALTA billete");
			System.out.println("[2] -- BAJA billete");
			System.out.println("[9] -- TERMINAR");
			System.out.print("Elija opcion: ");
			opcion = Integer.parseInt(teclado.nextLine());
 
			switch(opcion) {
			case 1:
				altaBillete();
				break;
			case 2:
				bajaBillete();
				break;
			case 9:
				System.out.println("\n\n\t\tFIN DE PROGRAMA");
				break;
			default:
				System.out.println("\nOpcion equivocada");
			}
		}while (opcion != 9);
 
	}
 
	private static void altaBillete() {
		System.out.println("\n\t\tALTA BILLETE");
		System.out.println("\nDatos del cliente");
		System.out.print("Identificador: ");
		String id = teclado.nextLine();
		System.out.print("Nombre: ");
		String nombre = teclado.nextLine();
		Cliente cliente = new Cliente(id, nombre);
 
		Trayecto trayecto = null;
		while(trayecto == null) {
			System.out.println("\nTrayecto");
			System.out.print("Origen:");
			String origen = teclado.nextLine();
			System.out.print("Destino:");
			String destino = teclado.nextLine();
			for (Trayecto tr: LISTA_TRAYECTOS) {
				if (tr.getOrigen().equals(origen) && tr.getDestino().equals(destino))
					trayecto = tr;
			}
 
			if (trayecto == null)
				System.out.println("No existe trayecto para esa ruta. Elija de nuevo.");
		}
 
		//Tenemos un cliente y un trayecto, podemos crear un billete.
		System.out.print("Quiere un billete de ida y vuelta?(S/N): ");
		char respuesta = teclado.nextLine().toUpperCase().charAt(0);
 
		Billete billete;
		if (respuesta == 'S')
			billete = new BilleteIdaVuelta(cliente, trayecto);
		else
			billete = new BilleteIda(cliente, trayecto);
 
		System.out.println("\nBillete creado");
		System.out.println(billete);
		billetes.add(billete);
	}
 
	private static void bajaBillete() {
		System.out.println("\n\t\tBAJA BILLETE");
		System.out.print("Indique su Identificador: ");
		String idCliente = teclado.nextLine();
 
		//Buscamos billetes asociados a este cliente
		System.out.println("\nBilletes asociados:");
		boolean encontrado = false;
		for (Billete bill: billetes) {
			if (bill.getCliente().getId().equals(idCliente)) {
				encontrado = true;
				System.out.println("-> " + bill.getIdBillete());
			}
		}
 
		if (!encontrado)
			System.out.println("No se han encontrado billetes.");
		else {
			System.out.println("Indique el billete que quiere dar de BAJA");
			System.out.print("Nº Billete: ");
			String idBillete = teclado.nextLine();
			Billete eliminado = null;
			for (int i = 0; i < billetes.size(); i++) {
				if (billetes.get(i).getIdBillete().equals(idBillete)) {
					eliminado = billetes.remove(i);
				}
			}
 
			if (eliminado == null)
				System.out.println("No hay billete con esa numeracion");
			else
				System.out.println("Se elimino este billete:\n" + eliminado);
		}
	}
 
	private static ArrayList<Trayecto> crearListadeTrayectos() {
		ArrayList<Trayecto> lista = new ArrayList<Trayecto>();
		lista.add(new Trayecto("Barcelona", "Madrid", 40));
		lista.add(new Trayecto("Barcelona", "Sevilla", 60));
		lista.add(new Trayecto("Barcelona", "Santiago", 60));
		lista.add(new Trayecto("Madrid", "Barcelona", 40));
		lista.add(new Trayecto("Madrid", "Santiago", 40));
		lista.add(new Trayecto("Madrid", "Sevilla", 40));
		lista.add(new Trayecto("Sevilla", "Madrid", 40));
		lista.add(new Trayecto("Sevilla", "Santiago", 60));
		lista.add(new Trayecto("Sevilla", "Barcelona", 60));
		lista.add(new Trayecto("Santiago", "Madrid", 40));
		lista.add(new Trayecto("Santiago", "Sevilla", 40));
		lista.add(new Trayecto("Santiago", "Barcelona", 40));
		return lista;
	}
 
}

Y ya está. Creo que ahí se trabaja prácticamente todos los aspectos de la POO.
Si crees que falta algo, como dijimos al principio, tienes libertad para incluir lo que quieras.

Pregunta si algo no se entiende.
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

AYUDA con ejercicio POO

Publicado por Alcides (2 intervenciones) el 26/03/2024 19:31:17
no entiendo nada
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

AYUDA con ejercicio POO

Publicado por Kabuto (1383 intervenciones) el 26/03/2024 21:25:11
¿Nada?

Si tienes conocimientos, al menos unas nociones, de programación orientada a objetos, entonces al menos sí entenderás por qué hemos hecho una clase Cliente, una clase Trayecto y como ambas se unen para componer la clase Billete

Pero si no tienes conocimientos de POO, entonces normal que el ejercicio resulte confuso. Antes tendrás que adquirir esos conocimientos.
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

AYUDA con ejercicio POO

Publicado por Alcides (2 intervenciones) el 02/04/2024 19:54:43
LA VERDAD SI, ME FALTA BASTANTE .
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