java - Setter métodos o constructores
(10)
Creo que hizo una buena pregunta: ¿Pero cuándo usamos constructores y cuándo usamos setters?
Primero, comencemos con algunos conceptos. Espero que esta explicación ayude a todos los que quieran saber cuándo usar constructores o métodos setters () y getters () (Accessors and Mutators). Los constructores son similares a los métodos , sin embargo, hay pocas diferencias entre el constructor y el método en java:
1) Constructor se usa para inicializar el estado de un objeto. El método se usa para exponer el comportamiento de un objeto.
2) El constructor no debe tener el tipo de devolución. El método debe tener un tipo de devolución.
3) El constructor se invoca implícitamente. El método se invoca explícitamente.
4) Getters () , o accessors, son métodos que proporcionan acceso a las variables de instancia de un objeto. Setters () , o mutators, son métodos que brindan al llamante la oportunidad de actualizar el valor de una variable de instancia particular.
Teniendo esto claro, pensemos en términos de Programación Orientada a Objetos (OOP), para cumplir con el requisito de los principios de OOP (La Programación Orientada a Objetos (OOP) se basa en cuatro principios principales : Encapsulación , Abstracción de Datos , Polimorfismo y Herencia .), Getter () y los métodos Setter () son la clave para lograr esto.
Aquí hay una fórmula que le mostrará lo que quiero decir:
Campos privados + Acceso público == Encapsulación;
Como puede ver basado en esta fórmula cuando establecemos campos privados y utilizamos accesos públicos, estamos realizando la encapsulación de uno de los 4 principios de OOP.
Aquí voy a ofrecer dos clases, agregué un comentario para intentar que mi código sea autoexplicativo. Tome estas clases como laboratorio de métodos con Customer
y TestCustomer
[la que tiene las clases de método main()
], puede copiar el código y ejecutarlo usted mismo. Tenga en cuenta que utilicé dos constructores para explicar una clase que tiene múltiples constructores y que tiene los métodos públicos setters()
y getters()
para acceder a variables de instancia privadas:
package com.exercise.lecture2;
/**
* 1) Create a Customer class that has the following attributes:
* name, SSN.
* 2) This class should have two methods: getName() and getSSN().
* 3) If the class is instantiated with only a SSN, then give the default name of "John Doe". (HINT: Use two constructors)
* 4) Also, add a method toString(), that returns a string representation of the customer object (name and SSN concatenated).
* Make sure to set this method public.
* 5) Create a class to test your program (e.g. a class that include the main() method). In your test program, instantiate
* three customers and print out the value using toString() method.
*
* @author Samuel M.
*
*/
//this class is complemented with class TestLabCustomer.java
public class LabCustomer {
// Private filds: name and socialSecurityNum
private String name;
private int socialSecurityNum;
// constructors
public LabCustomer(String name, int socialSecurityNum) {
this.name = name;
this.socialSecurityNum = socialSecurityNum;
}
/** The keyword ''this'' can be used to call a constructor from a constructor,
* when writing several constructor for a class, there are times when
* you''d like to call one constructor from another to avoid duplicate code.
*/
// Account with This() on a second constructor
public LabCustomer(int socialSecurityNum) {
this("John Doe", socialSecurityNum); // default name is printed if only the SSN is provided
}
// Public accessors (getters and setters)
String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
int getSSN() {
return socialSecurityNum;
}
void setSSN(int socialSecurityNum) {
this.socialSecurityNum = socialSecurityNum;
}
// instance method
public String toString() { //overriding the toString() method
return ("Customer name: " + getName() + ", SSN#: " + getSSN() ); // concatenating the name and SSN
}
}
Aquí está la clase de prueba, la que tiene el método main()
y llama a un método de instancia después de crear un objeto de la clase de vistas previas:
package com.exercise.lecture2;
//this class is complemented with class LabCustomer.java
public class TestLabCustomer {
public static void main(String[] args) {
// Instantiating an object of class LabCustomer and creating three customers objects
LabCustomer cust1 = new LabCustomer("Juan Melendez", 123457789);
LabCustomer cust2 = new LabCustomer("Mary Lee", 125997536);
LabCustomer cust3 = new LabCustomer(124963574); // when instantiating with no "name", the default (John Doe) is printed
/**
* Once you''ve instantiated an object and have an object variable,
* you can use object variable to call an instance method.
* e.g.:
* object variables: cust1, cust2, cust3
* call the method toString() using the object variable and dot [.] in order to perform the method call.
*/
// calling method toString() in class LabCustomer to print customer values
System.out.println(cust1.toString());
System.out.println(cust2.toString());
System.out.println(cust3.toString());
}
}
resultado:
Nombre del cliente: Juan Meléndez, Número de Seguro Social: 123457789
Nombre del cliente: Mary Lee, Número de Seguro Social: 125997536
Nombre del cliente: John Doe, Número de Seguro Social: 124963574
Hasta ahora he visto dos enfoques para establecer el valor de una variable en Java. A veces se usa un constructor con argumentos, otros métodos setter se usan para establecer el valor de cada variable.
Sé que un constructor inicializa una variable de instancia dentro de una clase una vez que se crea una instancia de una clase usando la palabra clave "nueva".
¿Pero cuándo usamos constructores y cuándo usamos setters?
Debe usar el enfoque de constructor, cuando desee crear una nueva instancia del objeto, con los valores ya llenos (un objeto listo para usar con valor poblado). De esta forma, no necesita sentarse explícitamente y llamar a los métodos setter para cada campo en el objeto para rellenarlos.
Establece el valor utilizando un enfoque de establecimiento, cuando desea cambiar el valor de un campo, después de que se haya creado el objeto.
Por ejemplo:-
MyObject obj1 = new MyObject("setSomeStringInMyObject"); // Constructor approach
// Yippy, I can just use my obj1, as the values are already populated
// But even after this I can change the value
obj1.setSomeString("IWantANewValue"); // Value changed using setter, if required.
..
MyObject obj2 = new MyObject();
obj2.setSomeString("setSomeStringNow"); // Setter approach
// values weren''t populated - I had to do that. Sad :(
Y como mencionó Axel, si desea crear objetos inmutables, no puede usar el método de métodos setter. No diré que todo tiene que ser inicializado en el constructor porque existen diferentes enfoques, como la evaluación diferida que se puede usar incluso con objetos inmutables .
Depende del dominio de aplicación y el propósito de la clase en él.
Los beans Java normalmente tienen un constructor no arg y getter / setters para variables de miembros relevantes. Hay ventajas en este enfoque, ya que los beans Java se admiten de forma predeterminada en muchos frameworks como Struts y Spring.
Una clase también puede imponer la disponibilidad obligatoria de valores haciendo pasar tales variables como parámetros a un constructor base. Y los valores no obligatorios se pueden establecer a través de otros constructores de conveniencia o métodos setter.
Por otro lado, las clases inmutables pueden tener constructores pero requieren métodos de ausencia que modifiquen su estado, incluidos los setters.
En general, tales decisiones se pueden tomar teniendo en cuenta el diseño general de la aplicación, los marcos 1 en los que se ejecuta, el contrato que debe hacer cumplir, etc.
1 - Aunque, se recomienda que el diseño de la clase sea independiente de los marcos. Los buenos marcos como Spring no hacen cumplir tales requisitos.
Digamos que tenemos una clase, llamada Contador:
public class Counter{
int count;
//constructor
public Counter(int c){
count = c;
}
public void setCounter(int newCounter){
count = newCounter;
}
}
En la clase anterior, cuando desee crear un nuevo objeto Contador, deberá usar un constructor y establecer la variable de conteo dentro de ese. al igual que:
Counter myCounter = new Counter(1);
Si quiere cambiar la variable de recuento durante el tiempo de ejecución , debería usar el método setter:
myCounter.setCounter(2);
En el caso de los constructores, cuando actualiza los campos, crea un nuevo objeto cada vez usando una palabra clave nueva .
Customer customer = new Customer("Tom", 23, 10000);
Por ejemplo, si desea actualizar el salario de Tom, debe volver a escribir esta línea con el salario actualizado, lo que significa que la memoria se desperdicia.
En el caso de los métodos de establecimiento, puede establecer campos individuales solo en el objeto original.
En la mayoría de los casos los uso a ambos :) (ya que 9/10 veces quiero volver y editar algo (y eso no es una buena práctica para hacer una nueva instancia)
Normalmente hago algo como tihs
public class User {
private int id;
private String initials;
private String firstName;
private String lastName;
private String email;
public User() {
this(0, "", "", "");
}
public User(int id, String firstName, String lastName, String email) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
// Getters and setters should be here
}
Y cuando quiera editar algo con él, puede usar los setters (algo bueno si, por ejemplo, está guardando a sus usuarios en una ArrayList, entonces puede obtener el objeto de la lista de arrays y simplemente establecer el campo que desea editar) , en lugar de hacer un objeto completamente nuevo :)
En lenguaje sencillo:
Use el constructor si cree que la inicialización del objeto es obligatoria antes de usar el objeto.
Use el método setter cuando la inicialización de la variable no sea obligatoria para usar el objeto.
Consulte la page documentación para más detalles.
Puedes combinar los dos enfoques. Dentro del constructor puedes invocar a los establecedores de variables de instancias. Algo como:
public class TestClass {
private String someField;
public TestClass(String someField) {
setSomeField(someField);
}
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
}
Si quieres tener un constructor de uso de clase inmutable, de lo contrario usa setters.
Usamos el enfoque dependiendo del escenario.
Si tenemos un conjunto de valores al crear una instancia del objeto de la clase, en ese momento utilizaremos el enfoque de constructor.
Cuando no conocemos el conjunto de valores mientras creamos la instancia del objeto en ese momento, usaremos el método setter.