Java - EJERCICIO POO

 
Vista:
sin imagen de perfil
Val: 25
Ha aumentado su posición en 3 puestos en Java (en relación al último mes)
Gráfica de Java

EJERCICIO POO

Publicado por joseba (7 intervenciones) el 02/05/2020 21:12:56
Tengo que entregar este ejercicio y me resulta muy difícil, no entiendo muchas de las cosas y mi profesora no es precisamente muy amigable. Si alguien me pudiera ayudar le estaría eternamente agradecido, es muy importante que lo entregue. Por aquí os dejo el ejercicio y lo que llevo hasta ahora. MUCHAS GRACIAS, PD: ES EL EJERCICIO2
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
-1
Responder
Imágen de perfil de Lisa
Val: 172
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

EJERCICIO POO

Publicado por Lisa (34 intervenciones) el 03/05/2020 19:12:07
¿Hola nene, podrías explicar de que se trata el ejercicio #2?
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
Val: 25
Ha aumentado su posición en 3 puestos en Java (en relación al último mes)
Gráfica de Java

EJERCICIO POO

Publicado por joseba (7 intervenciones) el 03/05/2020 22:39:38
Se trata de hacer un programa de gestión para una biblioteca, está todo el enunciado en el segundo rar
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

EJERCICIO POO

Publicado por Kabuto (1381 intervenciones) el 03/05/2020 20:13:16
Bufff. el enunciado es un poco... denso, pero ya lo voy desentrañando je je..

Por desgracia, ahora no tengo tiempo para seguir con esto.

Sí puedo mostrarte algunas correcciones de la clase Usuario que creo son necesarias.

Te pongo el código, contiene comentarios explicando los cambios respecto a tu código original.

Otra cosa, no me he podido poner por falta de tiempo como te digo, pero te adelanto que todo apunta a que la clase Verificador ha de ser abstracta.
De ella van a heredar las clases BlackList (para usuarios bloqueados) y , por ejemplo otra clase llamada CodigoSMS (la de usuarios que reciben código de verificación).
Al menos los métodos loginPaso1() y loginPaso2() también serían abstractos, ya que ambas clases: BlackList y CodigoSMS, tienen que implementarlos, pero con ciertas diferencias para cada uno.

A ver si mañana, puedo ayudarte con eso y el resto.

De momento, dale un vistazo a esta clase Usuario con los cambios que me han parecido pertinentes. Al menos por ahora, luego según avance el programa a lo mejor cambio de parecer.

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
132
133
134
135
136
public class Usuario {
 
	private String login, password;
	private LocalDate ultimo_acceso;
	private ArrayList<String> historial_password;
 
	public Usuario(String login, String password) {
		this.login = login;
		establecer_fecha(); //Este método puede ser tipo void, no es necesario que retorne nada
		this.password = password;
		this.historial_password = new ArrayList<String>();
		this.historial_password.add(password);
 
	}
 
	public Usuario() {
	}
 
	public String getLogin() {
		return login;
	}
 
	public String getPassword() {
		return password;
	}
 
	public void setPassword(String password) {
		this.password = password;
	}
 
	public LocalDate getUltimo_acceso() {
		return ultimo_acceso;
	}
 
	/*
	 * Siguiente método es innecesario. La gestión de la fecha de acceso
	 * se supone que ha de ser a nivel interno de la clase, no debería
	 * recibirse de forma externa, que es lo ofrece este método.
	 */
	/*
	public void setUltimo_acceso(LocalDate ultimo_acceso) {
		this.ultimo_acceso = ultimo_acceso;
	}*/
 
	/*
	 * Los dos siguientes métodos son innecesarios.
	 * EL historial de password se gestiona internamente.
	 * No hace falta, es más, no sería seguro, que puedan cambiarse
	 * u obtenerse de forma externa mediante métodos de tipo public.
	 */
	/*
	public ArrayList<String> getHistorial_password() {
		return historial_password;
	}
	public void setHistorial_password(ArrayList<String> historial_password) {
		this.historial_password = historial_password;
	}*/
 
	@Override
	public String toString() {
		return "Usuario{" + "login=" + login + ", ultimo_acceso=" + ultimo_acceso + ", password=" + password + ", historial_password=" + historial_password + '}';
	}
 
	/*
	 * Completo el siguiente método.
	 * Solo se puede modificar la contraseña si:
	 * - ha proporciondo la contraseña actual correctamente.
	 * - la nueva constraseña NO EXISTE en el historial de contraseñas.
	 * Esto último, el ArrayList nos proporciona un método para comprobarlo fácilmente.
	 */
	public boolean modificar_password(String password, String nueva_password) {
		if (validar(password) && !historial_password.contains(nueva_password)) {
			//contraseña valida y nueva contraseña NO esta CONTENIDA en el historial
			//Admitimos el cambio de contraseña
			this.password = nueva_password;
			//Actualizamos historial
			historial_password.add(nueva_password);
			return true;
		}
		else
			return false;
 
	}
 
	/*
	 * El siguiente método, su código funciona correctamente, pero contiene cosas innecesarios.
	 * No es necesario que informe de nada por pantalla con System.out.
	 * El programa principal que recibirá el resultado boolean, ya se encargará de
	 * informar por pantalla si es necesario.
	 * El try catch tampoco hace falta, no se está realizando ninguna operación
	 * que pueda provocar una excepción para capturar.
	 * El uso de palabras con letra ñ se desaconseja.
	 * Por último, por lo general, las contraseñas han de ser case sensitive,
	 * es decir, se ha de distinguir entre mayúsculas y minúsculas:
	 * Por ejemplo: Hola, hola, hOLA, HOLA, HoLa...
	 * deben ser consideradas contraseñas distintas, ergo, no debemos comparar con ignoreCase.
	 *
	 * Debajo pongo una versión de este método más sencilla y acorde con las necesidades
	 * que ha de cumplir.
	 */
	/*
	public boolean validar(String contraseña) {
		try {
			if (this.password.equalsIgnoreCase(contraseña)) {
				System.out.println("las contraseñas coinciden");
				return true;
			} else {
				System.out.println("Las contraseñas no coinciden");
				return false;
			}
		} catch (Exception e) {
			System.out.println("Error");
		}
		return false;
	}*/
 
	public boolean validar(String password) {
		return this.password.equals(password);
	}
 
	/*
	 * El siguiente método no es necesario que retorne nada.
	 * Puede ser de tipo void y modificar directamente el atributo
	 *
	 * Debajo hay una version alternativa.
	 */
	/*public LocalDate establecer_fecha() {
		return this.ultimo_acceso = LocalDate.now();
	}*/
 
	public void establecer_fecha() {
		ultimo_acceso = LocalDate.now();
	}
 
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar
sin imagen de perfil
Val: 25
Ha aumentado su posición en 3 puestos en Java (en relación al último mes)
Gráfica de Java

EJERCICIO POO

Publicado por joseba (7 intervenciones) el 03/05/2020 22:41:22
Madre mía, mil gracias, no sabes como me ayudas, llevo atascado con esto días. Me pondré a revisarlo de nuevo e intentar implementar tus consejos. Si tienes tiempo y te aburres mucho agradecería mucho cualquier otro aporte. GRACIAS DE NUEVO
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

EJERCICIO POO

Publicado por Kabuto (1381 intervenciones) el 04/05/2020 20:38:17
Jo, sigo pillado de tiempo. He avanzado más, a ver si consigo explicar rápido.
Clase usuario ya la tenemos. Si tienes dudas sobre ella pregunta.

Sobre la clase Verificador, como dije, parece ser que lo ideal es que esta clase sea abstracta. De ella heredarán BlackList y CodigoSMS.
Un Verificador lo que hace es recibir un login y un password.
Si contienen un usuario con esos datos, entonces se elabora un segundo paso, un desafío, que consiste en responder correctamente a una pregunta.
Esto podría ser Verificador:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public abstract class Verificador {
 
	//Puesto que el atributo login es la clave, el map se declara con String, no Integer
	//Podemos usar un HashMap, que no acepta duplicados, es decir, dos usuarios no podrán tener
	//el mismo login
    protected HashMap<String, Usuario> usuarios = new HashMap<String, Usuario>();
    //Los desafios, son datos String para token, Integer para respuesta
    protected HashMap<String, Integer> desafios = new HashMap<String, Integer>();
 
    public abstract String peticionDesafio(); //Devuelve una cadena con una pregunta
 
    public void nuevoUsuario(Usuario usuario)  {
    	usuarios.put(usuario.getLogin(), usuario);
    }
 
    public boolean borrarUsuario(Usuario usuario) {
    	return usuarios.remove(usuario.getLogin(), usuario);
    }
 
    public abstract String loginPaso1(String login, String password);
 
    public abstract boolean loginPaso2(String token, Integer respuesta);
 
}

Tiene dos HashMap (o usa solo Map si quieres).
Uno guarda Usuarios, usando como clave su atributo login.
El otro guarda desafíos. Estos desafíos se generan cuando el usuario supera el paso 1 de verificación. Los desafíos consisten en un token (un String aleatorio que se generar al superar el paso 1) y la respuesta correcta al desafío. Este dato lo he puesto como Integer porque las respuestas siempre son un número (nº al azar entre 0 y 999 o un número de mes), pero bueno, también se podría haber puesto como String.

Aquí menciono que no tiene mucho sentido usar un Map para guardar desafíos, porque los desafíos se crean tras el paso 1 y se destruyen tras el paso 2, tanto sí se supera como si no. Así que por muchos usuarios que tenga un verificador en su Map, en el Map de desafíos solo habrá un desafío (el del usuario que se intenta loguear) o ninguno.
Pero bueno, así lo pide el enunciado, pues venga.

Tiene métodos para agregar usuario y para eliminarlo.
Luego tiene tres métodos abstractos, estos métodos son asbtractos porque su código será distinto para cada clase hija que herede de Verificador. Así que están obligadas a tener estos métodos, pero cada uno con su propio código.

Veamos las clases hijas.
Una es un Verificador en el que para el segundo desafío se pide un número al azar que se simula recibir por SMS.
Tiene un atributo que es el número de intentos máximo que se puede intentar el segundo desafío. Este atributo se recibe por el constructor.
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
public class CodigoSMS extends Verificador{
 
	private int maxIntentos;
 
	public CodigoSMS(int intentos) {
		maxIntentos = intentos;
	}
 
	@Override
	public String peticionDesafio() {
		return "Introduzca códido SMS recibido: ";
	}
 
	@Override
	public String loginPaso1(String login, String password) {
 
		if (!usuarios.containsKey(login))
			return null;
		else if (!usuarios.get(login).validar(password))
			return null;
		else {
			String token = UUID.randomUUID().toString();
			/*
			 * Un verificador por código tiene como petición del desafío:
			 * “Introduzca el número que ha recibido por SMS”.
			 * La respuesta correcta al desafío es un único valor que se
			 * genera de forma aleatoria entre 0 y 999 (ambos incluidos).
			 */
			Random rnd = new Random();
			Integer respuesta = rnd.nextInt(1000);
			desafios.put(token, respuesta);
			System.err.println(respuesta);
			return token;
		}
	}
 
	@Override
	public boolean loginPaso2(String token, Integer respuesta) {
 
		if (maxIntentos == 0) {
			System.out.println("Se ha agotado el número de intentos máximo para superar desafío.");
			desafios.remove(token);
			return false;
		}
		else if (!desafios.containsKey(token))
			return false;
		else {
			System.out.println("Intentos restantes para superar desafío: " + maxIntentos);
			if (desafios.get(token).equals(respuesta)) {
				desafios.remove(token);
				return true;
			}
			else {
				maxIntentos--;
				desafios.remove(token);
				return false;
			}
		}
	}
 
	@Override
	public String toString() {
		return "Verificador tipo CodigoSMS.\n"
				+ "Máximo nº de intentos:" + maxIntentos
				+"\nCantidad usuarios registrados: " + usuarios.size();
	}
 
}

Los métodos que implementa son los que hereda de su clase madre, que como dijimos, el código será distinto para cada hija.
El método loginPaso1() vemos que comprueba que login y password son correctos.
Si lo son, genera el token, con él crea el desafío, y retorna el token
Este token retornado, luego en el programa main, tenemos que recogerlo en una variable para proceder al loginPaso2()
En el main, mostraríamos la pregunta desafío (nos la da el método peticionDesafio() ) y recogeríamos la respuesta del usuario.
Esta respuesta, junto al token que nos retornó loginPaso1(), se la pasaremos a loginPaso2()

loginPaso2() buscará el desafío correspondiente al token recibido y comprobará la respuesta. Sevovlerá true o false si se acierta o no.
En el caso de esta clase CodigoSMS, si se falla se restará un intento. Cuando los intentos lleguen a 0, ya siempre retornará false para este desafío.

No se si esto de los intentos, es así como quieren que se gestione. Yo lo hecho como me ha parecido más sensato a mi parecer...


Veamos ahora la clase BlackList.
Este Verificador es para almacenar usuarios bloqueados. El enunciado es algo confuso y no me queda claro si un Usuario al entrar en esta lista, se considera bloqueado automáticamente o no.
La lógica dice que sí, pero es que luego dice que alguien bloqueado no puede superar el loginPaso1()..., y sin embargo se explica como elaborar un desafío para loginPaso2().
Si alguien bloqueado no se le permite superar loginPaso1().., ¿para que narices queremos que esta clase tenga un loginPaso2()?

O quizás, no todos los usuarios dentro de una BlackList se consideran bloqueados (aunque el propio enunciado dice que BlackList alberga bloqueados), solo algunos (en base a no se que criterio) y de algún modo que no se especifica hay que establecer una distinción entre usuarios bloqueados y no bloqueados (a pesar de estar en BlackList)
¿Con un segundo Map quizás?

En fin, he pasado de filosofar sobre esto. Hagámoslo fácil y consideremos que bloqueado o no, el usuario tendrá su segundo desafío tal como describe el enunciado.

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
public class BlackList extends Verificador{
 
	@Override
	public String peticionDesafio() {
		return "Introduzca el día del mes de su último acceso:";
	}
 
	@Override
	public String loginPaso1(String login, String password) {
		if (!usuarios.containsKey(login))
    		return null;
    	else if (!usuarios.get(login).validar(password))
    		return null;
    	else {
    		String token = UUID.randomUUID().toString();
    		/*
    		 * un verificador blacklist tiene como petición del desafío:
    		 * “Introduzca el número del mes de su último acceso”.
    		 * Por tanto, la respuesta correcta al desafío será el texto
    		 * que corresponda al día del mes del último acceso del usuario
    		 *  al sistema.
    		 */
    		Integer respuesta = usuarios.get(login).getUltimo_acceso().getMonthValue();
    		desafios.put(token, respuesta);
    		return token;
    	}
	}
 
	@Override
	public boolean loginPaso2(String token, Integer respuesta) {
		if (!desafios.containsKey(token))
    		return false;
    	else if(!desafios.get(token).equals(respuesta)) {
    		desafios.remove(token);
    		return false;
    	}
    	else {
    		desafios.remove(token);
    		return true;
    	}
	}
 
	@Override
	public String toString() {
		return "Verificador tipo BlackList.\nCantidad usuarios registrados: " + usuarios.size();
	}
 
}

En este caso, no hay máximo de intentos. El segundo desafío solo pide indicar el número de mes del último acceso. El resto de mecánicas son las mismas que para la clase hermana CodigoSMS.


Bueno, pues ya tenemos Usuarios y Verificadores.
A continuación solo queda ponerlo a prueba en un main.

He seguido los pasos del enunciado, con alguna variación porque de nuevo pide alguna cosa confusa.
Crea los usuarios como pide.
Crea los dos tipos de Verificadores.
A cada uno lo he metido en un Verificador distinto.
Y entonces comienza un proceso cíclico donde se pide login y password.
Entonces se recorren los verificadores a ver quien lo tiene en su map, y si los datos son correctos, se inicia el segundo desafío que será distinto para cada tipo de Verificador.
Míralo a fondo, pruébalo y pregunta lo que no entiendas.

Falta lo de clonar verificadores, lo siento, habla de cosas que me suenan a chino: evitar aliasing, regla covariante....
Quizás tú si sepas de que va eso porque te lo habrán explicado en clase.

En cualquier caso, de momento centrate en comprender bien lo que hemos hecho hasta ahora. Y lo otro ya se verá.
Un saludo:
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
public class Main {
 
	private static Scanner teclado = new Scanner(System.in);
 
    public static void main(String[] args) {
 
    	/*
    	 * Crea un usuario con login “fperez” con password “lechemerengada”.
    	 * Modifica el password del usuario anterior estableciendo “cr7comeback”
    	 */
        Usuario u1 = new Usuario("fperez", "lechemerengada");
        System.out.println("Creado usuario u1:\n" + u1);
        pausa();
 
        if (u1.modificar_password("lechemerengada", "cr7comeback"))
        	System.out.println("La contraseña ha sido modificada");
        else
        	System.out.println("La contraseña no se pudo modificar");
        System.out.println("\nDatos actuales de u1:\n" + u1);
        pausa();
 
        //Crea un usuario con login “mlama” con password “tururu”.
        Usuario u2 = new Usuario("mlama", "tururu");
        System.out.println("Creado usuario u2:\n" + u2);
        pausa();
        /*
         * Crea un verificador blacklist y un verificador por código
         * con un máximo de 5 intentos.
         */
        BlackList verifBlack = new BlackList();
        System.out.println("Creado nuevo verificador:\n" + verifBlack);
        CodigoSMS verifSMS = new CodigoSMS(5);
        System.out.println("\nCreado nuevo verificador:\n" + verifSMS);
        pausa();
 
        /*
         * Declara y construye una lista de verificadores.
         * Añade los verificadores anteriores.
         */
        ArrayList<Verificador> verificadores = new ArrayList<Verificador>();
        verificadores.add(verifBlack);
        verificadores.add(verifSMS);
        /*
         * Recorre la lista de verificadores:
         * si el verificador es de tipo blacklist,
         * añade el usuario “mlama” como usuario bloqueado.
         */
        for (Verificador ver: verificadores) {
        	if (ver instanceof CodigoSMS) {
        		ver.nuevoUsuario(u1);
        	}
        	else if(ver instanceof BlackList) {
        		ver.nuevoUsuario(u2);
        	}
        }
        System.out.println("\nSe han añadido usuarios a los Verificadores.");
        System.out.println("\n" + verifBlack);
        System.out.println("\n" + verifSMS);
        pausa();
 
        //Poner a prueba sistema de login
        String login = "";
        do {
        	System.out.println("\nA continuacion introduzca el nombre de login.");
        	System.out.println("Para terminar proceso, pulse INTRO dejando el login en blanco.\n");
        	System.out.print("Login: ");
        	login = teclado.nextLine();
        	if (!login.isEmpty() || !login.isBlank()) {
        		System.out.print("Password: ");
            	String pass = teclado.nextLine();
 
            	String token = "";
            	for (Verificador verif: verificadores) {
            		token = verif.loginPaso1(login, pass);
            		if (token != null ) { //Paso1 superado
            			System.out.println(verif.peticionDesafio());
            			Integer resp = Integer.parseInt(teclado.nextLine());
 
            			if (verif.loginPaso2(token, resp)) {
            				System.out.println("\nLogin aceptado. Bienvenido");
            				break; //Dejamos de recorrer verificadores
            			}
            			else
            				System.out.println("\nDesafío no superado. Login rechazado");
            		}
            	}
 
            	if (token == null)
            		System.out.println("Login o Password desconocidos.");
        	}
 
 
        }while(!login.isEmpty() || !login.isBlank());
 
        System.out.println("\n\t\tFIN DEL PROGRAMA");
    }
 
    /**
     * Este método simplemente hace una pausa
     * deteniendo la ejecución del programa hasta que el
     * usuario pulse enter
     */
    private static void pausa() {
    	System.out.println("\n\t\tPulse INTRO para continuar...");
    	teclado.nextLine();
    }
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
3
Comentar
sin imagen de perfil
Val: 25
Ha aumentado su posición en 3 puestos en Java (en relación al último mes)
Gráfica de Java

EJERCICIO POO

Publicado por joseba (7 intervenciones) el 05/05/2020 12:00:30
Madre mía, no sé que decir. No existen las suficientes palabras de agradecimiento en nuestro vocabulario como para agradecer todo lo que siento.

Solo diré que ojalá pueda llegar a programar como tu algún día.
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

EJERCICIO POO

Publicado por Kabuto (1381 intervenciones) el 05/05/2020 16:39:50
Créeme, es más fácil de lo que parece. Es cuestión de tiempo y paciencia.
Y ojo, yo domino lo básico y poco más. Por aquí hay gente que me quintuplican en conocimientos

Pero por favor, sobre todo, no te conformes con obtener el código.
Asegúrate de que lo entiendes y pregunta cualquier duda que tengas, aunque te parezca que pueda ser tonta o insulsa.
Te ha de quedar claro cómo y por qué se generan las respuestas, que uso se le da a los token que se generan tras el paso1, etc..

En realidad lo que pide este ejercicio no es complejo, lo que pasa es que el enunciado no es demasiado claro. Pero está bien que no lo sea, eso exige al alumno un esfuerzo de comprensión extra e incluso tomar decisiones personales en cuanto a como llevar a cabo el ejercicio, ya que encontramos indicaciones que prácticamente se contradicen y otras que no son suficientes, así que depende de uno elegir cómo seguir adelante.

Y esto esta bien porque en la vida real, un cliente que te vaya a pedir un programa para su negocio, no te va a detallar que clases abstractas necesita, que atributos y métodos han de tener, que clases Java importar, etc...
El cliente lo que hará será explicar que datos gestiona y que resultados necesita de ellos. Ya luego el programador será quien decida que clases desarrollará y que lógica seguir.
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
Val: 25
Ha aumentado su posición en 3 puestos en Java (en relación al último mes)
Gráfica de Java

EJERCICIO POO

Publicado por joseba (7 intervenciones) el 12/05/2020 21:45:48
Muy buenas de nuevo, espero que todo te vaya genial.

Te hablaba de nuevo porque estoy con otro ejercicio que me está dando algunos problemas. Le tengo hecho ya entero, y es bastante más fácil que el anterior. Pero aún así me da problemas con el resultado final, ya que no me imprime nada por consola, ni siquiera errores. Es algo que no me había pasado jamás y no se como abordarlo.

Por aquí te dejo el enunciado del ejercicio y el código que llevo hasta ahora. Sería genial si le pudieras echar un vistazo y darme tu opinión.

MIL GRACIAS POR ADELANTADO
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

EJERCICIO POO

Publicado por Kabuto (1381 intervenciones) el 13/05/2020 20:38:09
Hola.
Pues mira, hay un fallito de esos tontos, que le pueden volver a uno loco hasta que lo descubre.

En la clase Cif, la entrada de datos con Scanner está antes que el mensaje. Eso hace que el programa no muestre nada en pantalla al empezar, pero en realidad está esperando que metas el cif

1
2
3
4
5
6
7
8
9
10
public class Cif {
 
    public static String recogerCif() {
        Scanner sc = new Scanner(System.in);
        String cif = sc.nextLine();
        System.out.println("Introduce el cif");
        return cif;
    }
 
}

Mejor cambiar el orden

1
2
3
4
5
6
7
8
9
10
public class Cif {
 
    public static String recogerCif() {
        Scanner sc = new Scanner(System.in);
        System.out.println("Introduce el cif");
        String cif = sc.nextLine();
        return cif;
    }
 
}

Ahora se pueden meter los 3 cif, pero luego el programa termina sin mostrar más mensajes. ¿Por qué?
El siguiente inconveniente lo encontramos en este método:

1
2
3
4
5
6
7
8
public void solicitud(Empresa empresa) {
 
        for (int i = 0; i < empresas_solicitantes.size(); i++) {
            empresas_solicitantes.add(empresa);
            System.out.println("empresa añadida");
        }
 
    }
Ahí le estás diciendo que el bucle se repita desde 0, hasta el tamaño de empresas_solicitantes.
¿Y que tamaño tiene este Set la primera vez que arranca el programa? Pues tamaño 0
De 0 a 0, pues va 0.
Es decir, ese bucle se repite 0 veces y por lo tanto la empresa no se añade.

De hecho, no se requiere ningún bucle para añadir la empresa solicitante. Se añade y punto.
1
2
3
4
5
public void solicitud(Empresa empresa) {
 
    	empresas_solicitantes.add(empresa);
        System.out.println("empresa añadida");
    }

Guay. Ahora ya si se añaden las empresas.
Pero tenemos un nuevo error:
1
2
3
4
5
6
7
8
9
10
11
12
Introduce el cif
sfdas
Introduce el cif
asfdsa
Introduce el cif
asdfas
empresa añadida
empresa añadida
empresa añadida
Estas empresas están en espera:
 Empresa{nombre=mercadona, fecha_creacion=2019-11-12, fecha_alta=null, numero_trabajadores=11, cif=sfdas}
Exception in thread "main" java.util.ConcurrentModificationException

ConcurrentModification, ¿que es eso? Pues se debe a este método.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void mostrar() {
 
        for (Empresa lista : empresas_solicitantes) {
            System.out.println("Estas empresas están en espera: \n " + lista.toString());
            empresas_solicitantes.remove(lista);
 
        }
 
        for (Empresa lista : empresas_aceptadas) {
            System.out.println("Estas empresas están dadas de alta en la asociación: \n" + lista.toString());
            empresas_aceptadas.remove(lista);
 
        }
 
        for (Empresa lista : empresas_rechazadas) {
            System.out.println("Estas empresas fueron rechazadas: \n" + lista.toString());
            empresas_rechazadas.remove(lista);
        }
    }

En esos bucles for, lo que está pasando es que el bucle for se posiciona en una empresa del Set, muestra sus datos, y acto seguido se da orden de removerla del set.
Pero esto es un problema, el for está recorriendo ese set, ya ha calculado lo que mide, pero si tu le vas quitando elementos, le estás fastidiando al for los cálculos que se había hecho previamente.
Vamos, que mientras el for esté recorriendo el set, no puedes modificar su tamaño quitando o agregando elementos.

Por cierto, además estás removiendo todas las empresas. Pero el enunciado dice eliminar solo las rechazadas

¿Como eliminarlas? Pues primero las muestras, y luego te las cargas con el método clear(), ya fuera del bucle.
Por cierto, los mensajes tipo "Estas empresas están en espera..." mejor ponerlos fuera del bucle para que solo aparezcan una vez.
Si no, aparecerá una vez por cada empresa que tenga el set.
Y mejor si comprobamos primero si hay empresas para mostrar o no.

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
public void mostrar() {
 
    	if (empresas_solicitantes.isEmpty())
    		System.out.println("\nNo hay empresas en espera");
    	else {
	    	System.out.println("\nEstas empresas estan en espera:");
	        for (Empresa lista : empresas_solicitantes)
	            System.out.println(lista);
    	}
 
    	if (empresas_aceptadas.isEmpty())
    		System.out.println("\nNo hay empresas dadas de alta en la asociación.");
    	else {
	        System.out.println("\nEstas empresas están dadas de alta en la asociación:");
	        for (Empresa lista : empresas_aceptadas)
	            System.out.println(lista);
    	}
 
    	if (empresas_rechazadas.isEmpty())
    		System.out.println("\nNo hay empresas rechazadas");
    	else {
	        System.out.println("Estas empresas fueron rechazadas:");
	        for (Empresa lista : empresas_rechazadas)
	            System.out.println(lista);
 
	        empresas_rechazadas.clear(); //Empresas rechazadas son eliminadas
    	}
    }

Bueno, con todos estos cambios el programa ya muestra cosas en pantalla y sin errores.

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
Introduce el cif
sdafas
Introduce el cif
asdfa
Introduce el cif
asdfa
empresa añadida
empresa añadida
empresa añadida
 
Estas empresas estan en espera:
Empresa{nombre=mercadona, fecha_creacion=2019-11-12, fecha_alta=null, numero_trabajadores=11, cif=sdafas}
Empresa{nombre=aldi, fecha_creacion=2015-11-12, fecha_alta=null, numero_trabajadores=5, cif=asdfa}
Empresa{nombre=carefour, fecha_creacion=2020-01-12, fecha_alta=null, numero_trabajadores=4, cif=asdfa}
 
No hay empresas dadas de alta en la asociación.
 
No hay empresas rechazadas
 
Estas empresas estan en espera:
Empresa{nombre=mercadona, fecha_creacion=2019-11-12, fecha_alta=null, numero_trabajadores=11, cif=sdafas}
Empresa{nombre=aldi, fecha_creacion=2015-11-12, fecha_alta=null, numero_trabajadores=5, cif=asdfa}
Empresa{nombre=carefour, fecha_creacion=2020-01-12, fecha_alta=null, numero_trabajadores=4, cif=asdfa}
 
No hay empresas dadas de alta en la asociación.
 
No hay empresas rechazadas

Sin embargo, parece que el método verificar() no está cumpliendo con su cometido. No está dando de alta las empresas.
Revísalo a ver que puede estar fallando. Si no lo consigues dilo y te echamos una mano.
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
Val: 25
Ha aumentado su posición en 3 puestos en Java (en relación al último mes)
Gráfica de Java

EJERCICIO POO

Publicado por joseba (7 intervenciones) el 14/05/2020 20:09:47
He corregido lo que me has dicho y me ha funcionado, muchas gracias. Sin embargo, el método verificar me da también el error Exception in thread "main" java.util.ConcurrentModificationException.

He probado a intentar recorrerlo con un Iterator y con un for each pero en ambos me da el error y no se como solucionarlo. Creo que puede ser lo que tu comentabas: que al borrar una empresa se modifica el tamaño de la colección y el bucle se hace un lío pero, sinceramente, no estoy seguro de nada.

Estas son las dos opciones que se me han ocurrido, pero parece que ambas provocan lo mismo

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 void verificar() {
 
    /*
    Con el Iterator
    */
    Iterator<Empresa> it = empresas_solicitantes.iterator();
    while (it.hasNext()) {
        Empresa next = it.next();
        if (next.getFecha_creacion().isAfter(LocalDate.now().minusYears(2)) && next.getNumero_trabajadores() > 3) {
 
            empresas_solicitantes.remove(next);
            empresas_aceptadas.add(next);
            System.out.println("Empresa: " + next.getCif() + " eliminada de solicitantes y dada de alta");
            next.setFecha_alta(LocalDate.now());
 
        } else {
            System.out.println("Empresa: " + next.getCif() + " no dada de alta");
            empresas_rechazadas.add(next);
        }
    }
    /*
    Con el for each
     */
    for (Empresa empresa : empresas_solicitantes) {
        if (empresa.getFecha_creacion().isAfter(LocalDate.now().minusYears(2)) && empresa.getNumero_trabajadores() > 3) {
 
            empresas_solicitantes.remove(empresa);
            empresas_aceptadas.add(empresa);
            System.out.println("Empresa: " + empresa.getCif() + " eliminada de solicitantes y dada de alta");
            empresa.setFecha_alta(LocalDate.now());
 
        } else {
            System.out.println("Empresa: " + empresa.getCif() + " no dada de alta");
            empresas_rechazadas.add(empresa);
        }
    }
}
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

EJERCICIO POO

Publicado por Kabuto (1381 intervenciones) el 14/05/2020 22:02:34
A ver si con tiempo lo reviso.
Hoy imposible

Pero veo que haces remove() al mismo tiempo que recorres los set. Por eso da ese error.

No se pueden modificar los set mientras se recorren. Habrá que pensar en otra lógica distinta.
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
Val: 25
Ha aumentado su posición en 3 puestos en Java (en relación al último mes)
Gráfica de Java

EJERCICIO POO

Publicado por joseba (7 intervenciones) el 17/05/2020 17:16:14
Muy buenas,

seguí con ello y al final creo que encontré la solución, te la dejo por aquí por si tenías curiosidad o algo jejeje. Era cuestión de borrar las empresas una vez finalizado el bucle, y no dentro de él.

Muchas gracias por todo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void verificar() {
 
    /*
    Con el Iterator
     */
    Iterator<Empresa> it = empresas_solicitantes.iterator();
    while (it.hasNext()) {
        Empresa next = it.next();
        if (next.getFecha_creacion().isAfter(LocalDate.now().minusYears(2)) && next.getNumero_trabajadores() > 3) {
 
            empresas_aceptadas.add(next);
            System.out.println("\nEmpresa: " + next.getCif() + " eliminada de solicitantes y dada de alta");
            next.setFecha_alta(LocalDate.now());
 
        } else {
            System.out.println("\nEmpresa: " + next.getCif() + " no dada de alta");
            empresas_rechazadas.add(next);
        }
    }
    empresas_solicitantes.clear();
}
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