Getters y setters
Un atributo public puede ser modificado desde cualquier clase, lo que hace que a veces tenga sus inconvenientes, ya que es imposible controlar los valores asignados, que pueden no tener sentido. Por ejemplo, nada impide que se asigne a un atributo edad un valor negativo, algo incoherente.
Por este motivo existe una convención en la comunidad de programadores de ocultar los atributos y en lugar de eso crear dos métodos: el primero (set) permite asignar un valor al atributo; y el segundo (get) devuelve un atributo para conocer su valor.
Los métodos se identifican con set/get seguido del nombre del atributo. Ejemplo:
public class Persona{
private int edad;
// solo modificamos la edad si recibimos una edad mayor que cero
public void setEdad(int edad){
if(edad > 0){
this.edad = edad;
}
}
public int getEdad(){
return this.edad;
}
}
Las ventajas de utilizar estos métodos es que la implementación se encapsula ocultando los detalles de la misma.
Para crear automáticamente getters y setters en VSC dentro de una clase hacemos click con el botón derecho y en el menú seleccionamos Source Action... y a continuación Generate Getters o Generate Setters según el caso.
Utilización de setters en el constructor para asignación de valores
Los setters permiten realizar validaciones de los datos antes de asignarlos a los atributos. Si se emplean directamente los atributos dentro del constructor sin pasar por los setters, puede que pierdas la oportunidad de validar los datos. Por ejemplo:
public class Persona{
private int edad;
public Persona(int edad) {
this.setEdad(edad); // Usamos el setter
}
// solo modificamos la edad si recibimos una edad mayor que cero
public void setEdad(int edad){
if(edad > 0){
this.edad = edad;
}
}
public int getEdad(){
return this.edad;
}
}
De este modo, si el valor de edad no es válido, el setter asegurará que nunca se asigne un valor incorrecto. Así también evitas repetir la misma validación en el constructor y en cualquier otro punto donde se necesite establecer el valor.
Además, si en el futuro necesitas cambiar la lógica al establecer un atributo, solo necesitas actualizar el setter, y el constructor seguirá funcionando correctamente. Esto ayuda a mantener el código más limpio y flexible.
Getters de atributos inexistentes
Crear un getter para un atributo inexistente puede parecer un concepto confuso, ya que, en general, los getters son métodos utilizados para acceder a atributos privados de un objeto. No obstante, hay algunos escenarios donde se puede considerar la creación de getters que no están directamente vinculados a atributos de instancia concretos.
Por ejemplo, un getter puede devolver un valor que se calcula a partir de los atributos existentes, en lugar de acceder a un atributo específico. En estos casos, no hay un "atributo" en el sentido tradicional, sino que el getter proporciona un resultado que es el resultado de una operación o cálculo.
public class Circulo {
private double radio;
public Circulo(double radio) {
this.radio = radio;
}
// Getter que calcula el área del círculo en vez de devolver un atributo
public double getArea() {
return Math.PI * radio * radio; // Calcula el área
}
}
Se puede crear un getter que retorne un valor que depende del estado actual del objeto o de la interacción con otros objetos. Estas propiedades computadas son útiles para encapsular la lógica que se necesita para obtener el valor.
public class Persona {
private String nombre;
private String apellido;
public Persona(String nombre, String apellido) {
this.nombre = nombre;
this.apellido = apellido;
}
// Getter que devuelve el nombre completo
public String getNombreCompleto() {
return nombre + " " + apellido; // Combina nombre y apellido
}
}
Los getters también se pueden usar para acceder a información que no está directamente almacenada como atributo, sino que depende del estado de otros objetos.
public class Tienda {
private List<Producto> productos;
public Tienda(List<Producto> productos) {
this.productos = productos;
}
// Getter que devuelve el número de productos en la tienda
public int getNumeroDeProductos() {
return productos.size(); // Obtiene el número total de productos
}
}