Java - Ayuda con constructores

 
Vista:

Ayuda con constructores

Publicado por Ricardo (2 intervenciones) el 08/01/2019 11:41:55
Buenas a tod@s. Soy nuevo en esto de la programación, y sé que la pregunta que voy a hacer es súper básica, pero llevo mirando páginas bastantes días sin que me aclaren nada.
Veréis, el ejercicio me pide que cree una clase Artículo, definir unas variables y añadir métodos para consultar y modificar los valores (getters y setters). Esta parte está hecha, y creo que es así:
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
import java.util.Scanner;;
 
public class Articulo {
    private Scanner teclado;
    private String codigo_barra;
    private String denominacion;
    private int unidades;
    private double precio_compra;
    private int beneficio;
    private double pvp;
 
    public Articulo(){
        teclado = new Scanner(System.in);
 
        System.out.println("El código de barra es: ");
        codigo_barra = teclado.next();
        System.out.println("Denominación: ");
        denominacion = teclado.next();
        System.out.println("Unidades: ");
        unidades = teclado.nextInt();
        System.out.println("Beneficio: ");
        beneficio = teclado.nextInt();
        pvp = precio_compra+((precio_compra*beneficio)/100);
        System.out.println("PvP: " + pvp);
    }
 
	public String getCodigo_barra() {
		return codigo_barra;
	}
	public void setCodigo_barra(String codigo_barra) {
		this.codigo_barra = codigo_barra;
	}
	public String getDenominacion() {
		return denominacion;
	}
	public void setDenominacion(String denominacion) {
		this.denominacion = denominacion;
	}
	public int getUnidades() {
		return unidades;
	}
	public void setUnidades(int unidades) {
		this.unidades = unidades;
	}
	public double getPrecio_compra() {
		return precio_compra;
	}
	public void setPrecio_compra(double precio_compra) {
		this.precio_compra = precio_compra;
	}
	public int getBeneficio() {
		return beneficio;
	}
	public void setBeneficio(int beneficio) {
		this.beneficio = beneficio;
	}
	public double getPvp() {
		return pvp;
	}
	public void setPvp(double pvp) {
		this.pvp = pvp;
	}
}


Posteriormente me dice que debo crear una clase EntradaArticulos, con un método main y tres objetos (articulo1, articulo2 y articulo3). En el primero debo inicializar los atributos de la entrada por teclado de esos datos. Por lo que creo que quedaría así:

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 class EntradaArticulos {
 
	public static void main (String[] args) {
 
		EntradaArticulos articulo1 = new EntradaArticulos();
 
		Articulo articulo = new Articulo();
 
 
		Articulo cb = new Articulo();
		String codigo_barra = cb.getCodigo_barra();
 
		Articulo den = new Articulo();
		String denonminacion = den.getDenominacion();
 
		Articulo un = new Articulo();
		int unidades = un.getUnidades();
 
		Articulo pCompra = new Articulo();
		double precio_compra = pCompra.getPrecio_compra();
 
		Articulo bfc = new Articulo();
		int beneficio = bfc.getBeneficio();
 
		Articulo pVenta = new Articulo();
		double pvp = pVenta.getPvp();
      }
}

En el segundo objeto (articulo2), debo instanciar e inicializar llamando al constructor donde se le pasan como parámetros las variables locales declaradas en el main, cuyos valores se han pedido por teclado,

Agradezco vuestra ayuda. Un saludo
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 constructores

Publicado por Kabuto (1381 intervenciones) el 08/01/2019 13:47:02
Hola.

En principio, cuando creamos una clase que va a representar un objeto : un Articulo, una Persona, un Estudiante, un PartidoFutbol, un Vehiculo, etc..... su constructor no debería pedir datos por teclado.

Se puede hacer, e incluso puede que tú como programador en algún caso muy concreto decidas hacerlo así, porque te ha dado la real gana..faltaría más.. xD

Sin embargo, en general estas clases se han de encargar básicamente de definir el objeto que representan y de ser capaz de recibir datos para sus atributos (SETTERS) y proporcionarlos (GETTERS).
Pero no deberían encargarse de pedir dichos datos para los atributos.

Esos datos ya se encargará de pedirlos otro programa. Además, en el mundo real, muchas veces esos datos para los atributos pueden ser recibidos por otros medios distintos del teclado: una base de datos, un formulario web, de otro objeto Articulo creado previamente...

Por tanto, si creamos para nuestra clase un Constructor como el que tú has hecho que forzosamente pide datos por la consola de texto, esto será muy poco funcional y traería muchos inconvenientes.
Imagina que quisieramos usar tu clase Artículo para un programa que accede a una base de datos con los atributos necesarios para crear 1000 artículos y queremos que los recoja e inicialice esos 1000 articulos automáticamente, sin intervención humana ninguna.
Tu clase Articulo no serviría, porque al intentar inicializar el primer artículo, el programa se quedaría esperando que alguien teclee el codigo de barras por teclado.... cuando se supone que ese dato lo va a recibir de una base de datos.

Tu clase ha de ser aprovechable para cualquier tipo de programa, tanto los que van a pedir datos por teclado, como los que no...por eso no deberías incluir ningún Scanner en tu clase.


Los Constructores, por lo general, solo han de encargarse de inicializar los valores de los atributos. Si es un constructor que SI recibe parametros, los inicializará a valores cero.
Si es un constructor que SÍ recibe parámetros, asignará el valor de esos parámetros a los correspondientes atributos.
Habrá casos en los que necesitemos que el contructor haga algo más que solo asignar valores, por ejemplo en esta clase Artículo necesitamos que el atributo PVP lo autocalcule en base a los atributos precio compra y beneficio.
Pero a parte de pequeñas cosas como esta, poco más debería hacer.


Una clase puede tener varios constructores distintos, y luego el programa que utilice nuestra clases podrá usar un constructor u otro según le convenga.

Mira, he escrito una clase Articulo que va a tener 3 constructores.
- Un constructor que no recibe parametros
- Otro que solo recibe el codigo de barras y la denominación, que podrían ser los atributos mínimos para distinguir un artículo de otro.
- Por último, un constructor que recibe de golpe TODOS los parámetros necesarios para definir los atributos

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
public class Articulo {
 
	private String codigo_barra;
	private String denominacion;
	private int unidades;
	private double precio_compra;
	private int beneficio;
	private double pvp;
 
	//Podemos definir solo uno, o varios constructores
 
	//Constructor básico que NO recibe datos e inicializa atributos a valores básicos.
	//Esto nos daría un ARTICULO completamente indefinido y luego habría que usar SETTERS para empezar a definirlo
	//ya que si no, sería imposible poder operar con este objeto
	public Articulo()
	{
		codigo_barra = "";
		denominacion = "";
		unidades = 0;
		precio_compra = 0d; //La d es para indicar que ese 0 es un double, no es estrictamente necesario hacer esta indicacion
		beneficio = 0;
		pvp = 0d;
	}
 
	//Constructor que solo recibe unos DATOS MÍNIMOS para definir el ARTICULO.
	//Tendríamos un objeto con al menos un codigo de barras y una denominación, datos suficientes
	//para por ejemplo mostrar una descripción básica en pantalla o guardarlo en una base de datos.
	public Articulo(String barra, String denom)
	{
		codigo_barra = barra; //Recogemos los datos mínimos obtenidos por parámetros
		denominacion = denom;
		unidades = 0; //El resto de atributos reciben valores básicos de inicializacion
		precio_compra = 0d;
		beneficio = 0;
		pvp = 0d;
	}
 
	//Contructor COMPLETO que recibirá por parámetros todos los datos necesarios para describir un ARTICULO
	//Esto nos dará un objeto completamente definido en una sola línea
	public Articulo(String barra, String denom, int unid, double precioCompra, int benef)
	{
		codigo_barra = barra;
		denominacion = denom;
		unidades = unid;
		precio_compra = precioCompra;
		beneficio = benef;
		pvp = precio_compra+((precio_compra*beneficio)/100);//Aquí si tenemos datos suficientes para calcular PVP
	}
 
	public String getCodigo_barra() {
		return codigo_barra;
	}
 
	public void setCodigo_barra(String codigo_barra) {
		this.codigo_barra = codigo_barra;
	}
 
	public String getDenominacion() {
		return denominacion;
	}
 
	public void setDenominacion(String denominacion) {
		this.denominacion = denominacion;
	}
 
	public int getUnidades() {
		return unidades;
	}
 
	public void setUnidades(int unidades) {
		this.unidades = unidades;
	}
 
	public double getPrecio_compra() {
		return precio_compra;
	}
 
	public void setPrecio_compra(double precio_compra) {
		this.precio_compra = precio_compra;
	}
 
	public int getBeneficio() {
		return beneficio;
	}
 
	public void setBeneficio(int beneficio) {
		this.beneficio = beneficio;
	}
 
	public double getPvp() {
		return pvp;
	}
 
}


Y a continuación he creado la clase EntradaArticulos, que será el programa que se encargará de inicializar los tres objetos Artículo.
Es esta clase la que se ha de encargar de pedir los datos por teclado y propocionárselos a los constructores de nuestra clase Artículo.

Para experimentar con los tres constructores, para cada Articulo uso un constructor distinto. Para todos habrá que pedir datos por teclado obviamente, la diferencia es que a algunos dichos datos se los pasaremos usando los SETTERS y para otros se los pasaremos directamente al 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
import java.util.Scanner;
 
public class EntradaArticulos {
 
	public static void main(String[] args) {
 
		Scanner teclado = new Scanner(System.in);
 
		//Hay que crear tres artículos.
		//A modo de ejemplo práctico, usaremos uno constructor diferente para cada uno
 
		//Primer artículo: Contructor sin parametros. Habrá que pedir por SETTERS todos los datos
		System.out.println("\t\tCreando ARTICULO 1");
		Articulo articulo1 = new Articulo();
		System.out.print("Introduzca CODIGO de BARRAS: ");
		articulo1.setCodigo_barra(teclado.nextLine());
		System.out.print("Introduzca DENOMINACION: ");
		articulo1.setDenominacion(teclado.nextLine());
		System.out.print("Introduzca UNIDADES: ");
		articulo1.setUnidades(Integer.parseInt(teclado.nextLine()));
		System.out.print("Introduzca PRECIO de COMPRA: ");
		articulo1.setPrecio_compra(Double.parseDouble(teclado.nextLine()));
		System.out.print("Introduzca BENEFICIO: ");
		articulo1.setBeneficio(Integer.parseInt(teclado.nextLine()));
 
		articulo1.setPvp(articulo1.getPrecio_compra() +((articulo1.getPrecio_compra() * articulo1.getBeneficio())/100));
 
		//Segundo articulo: Contructor con parametros mínimos. El resto se piden por SETTERS
		System.out.println("\n\t\tCreando ARTICULO 2");
		System.out.print("Introduzca CODIGO de BARRAS: ");
		String barras = teclado.nextLine();
		System.out.print("Introduzca DENOMINACION: ");
		String denom = teclado.nextLine();
 
		Articulo articulo2 = new Articulo(barras, denom);
 
		System.out.print("Introduzca UNIDADES: ");
		articulo2.setUnidades(Integer.parseInt(teclado.nextLine()));
		System.out.print("Introduzca PRECIO de COMPRA: ");
		articulo2.setPrecio_compra(Double.parseDouble(teclado.nextLine()));
		System.out.print("Introduzca BENEFICIO: ");
		articulo2.setBeneficio(Integer.parseInt(teclado.nextLine()));
 
		articulo2.setPvp(articulo2.getPrecio_compra() +((articulo2.getPrecio_compra() * articulo2.getBeneficio())/100));
 
		//Tercer articulo: Contructor COMPLETO. No será necesario usar SETTERS
		System.out.println("\n\t\tCreando ARTICULO 3");
		System.out.print("Introduzca CODIGO de BARRAS: ");
		barras = teclado.nextLine();
		System.out.print("Introduzca DENOMINACION: ");
		denom = teclado.nextLine();
		System.out.print("Introduzca UNIDADES: ");
		int unidades = Integer.parseInt(teclado.nextLine());
		System.out.print("Introduzca PRECIO de COMPRA: ");
		double precioCompra =  Double.parseDouble(teclado.nextLine());
		System.out.print("Introduzca BENEFICIO: ");
		int beneficio =  Integer.parseInt(teclado.nextLine());
 
		Articulo articulo3 = new Articulo(barras, denom, unidades, precioCompra, beneficio);
 
		System.out.println("\n\t\tFIN DE PROGRAMA");
		teclado.close();
	}
 
}

Resumiendo, por lo general, un constructor de una clase no ha de encargarse de pedir datos (salvo que tengamos muy claro que deseamos que sea así porque a dicha clase le vamos a dar un uso muy determinado). Los datos ya se encargará otro programa de obtenerlos y proporcionarselo al constructor de nuestra clase.

Nuestra clase puede tener varios constructores. No hay un constructor mejor que otro. La decisión de si proporcionar un constructor o varios, o de si los constructores recibirán por parámetros TODOS los valores de los atributos o solo algunos, dependerá en cada caso según la naturaleza del objeto, las necesidades del programa final, etc...

Normalmente nos va a interesar propocionar un contructor que admita TODOS los parámetros y otro constructor que admita al menos los parámetros mínimos para distinguir de forma única un objeto de otro.
Por ejemplo, para crear una clase Vehículo. Un Vehículo puede tener muchos atributos: color, peso, marca, modelo, numero de plazas, precio, año fabricacion,......

Y la mayoría son atributos comunes que pueden repetirse en muchos vehículos distintos, no van a servir para distinguir de forma única un Vehiculo de otro.
Sin embargo, hay algún atributo que si será único, por ejemplo el número de bastidor y/o la matrícula.
Así que al crear un objeto Vehículo, sería bueno disponer de un constructor que como mínimo, nos admita proporcionarle esos atributos únicos.


Por último, una pequeña aclaracion final.
Puede que te haya resultado extraño que para pedir datos numéricos por teclado, lo que hago es pedirlos usando nextLine(), quien nos proporciona un String con lo que ha tecleado el usuario, y luego los "parseo" a valor int con Integer.parseInt() o a double Double.parseDouble()

Hay tres motivos por los que hago esto:
1 - La clase Scanner a veces hace cosas raras cuando en el mismo programa la usamos para pedir datos String y datos numéricos en el mismo proceso.
Para evitar estas "cosas raras", lo que hago es pedirle solo Strings, y ya luego los parseo al tipo de datos que necesito.

2- En el futuro, cuando empieces a crear y a usar ventantas Java (la clase Swing), con botones, campos de texto, etc... los datos que obtengamos del usuario SIEMPRE los vamos a recibir como String, y siempre vamos a tener que parsearlos al tipo de dato que necesitemos.
Así que no viene mal ir cogiendo ya la costumbre de hacer esto...

3- Otros lenguajes de programacion como C#, que es muy similar a Java, es también costumbre tratar los datos de este modo: pedir Strings y luego parsear.
Así que de nuevo es interesante acostumbrarse a este procedimiento
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

Ayuda con constructores

Publicado por Ricardo (2 intervenciones) el 09/01/2019 09:51:54
Muchísimas gracias. Te mereces una estatua! De verdad, mil 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