CodeGym /Blog Java /Random-ES /Getters y setters
Autor
Vasyl Malik
Senior Java Developer at CodeGym

Getters y setters

Publicado en el grupo Random-ES
¡Hola! En lecciones anteriores, ya aprendiste cómo declarar tus propias clases completas con métodos y campos. En la lección de hoy, hablaremos sobre Getters y Setters en Java. Este es un progreso serio, ¡bien hecho! Pero ahora tengo que contarte una verdad desagradable. ¡No declaramos nuestras clases correctamente! ¿Por qué? A primera vista, la siguiente clase no tiene ningún error:

public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}
Pero lo hace. Imagina que estás sentado en el trabajo y escribes esta clase Cat para representar a los gatos. Y luego te vas a casa. Mientras no estás, otro programador llega al trabajo. Crea su propia clase principal , donde comienza a usar la clase Cat que escribiste.

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
No importa por qué lo hizo y cómo sucedió (quizás el tipo está cansado o no durmió lo suficiente). Algo más importa: nuestra clase Cat actual permite que se asignen valores absolutamente locos a los campos. Como resultado, el programa tiene objetos con un estado no válido (como este gato que tiene -1000 años). Entonces, ¿qué error cometimos al declarar nuestra clase? Expusimos los datos de nuestra clase. Los campos de nombre, edad y peso son públicos. Se puede acceder a ellos desde cualquier parte del programa: simplemente cree un objeto Cat y cualquier programador tendrá acceso directo a sus datos a través del operador punto ( . ).

Cat cat = new Cat();
cat.name = "";
Aquí estamos accediendo directamente al campo de nombre y configurando su valor. Necesitamos proteger de alguna manera nuestros datos de interferencias externas inapropiadas. ¿Qué necesitamos para hacer eso? Primero, todas las variables de instancia (campos) deben marcarse con el modificador privado. Private es el modificador de acceso más estricto en Java. Una vez que haga esto, los campos de la clase Cat no serán accesibles fuera de la clase.

public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";//error! The Cat class's name field is private!
   }
}
El compilador ve esto e inmediatamente genera un error. Ahora los campos están algo protegidos. Pero resulta que hemos cerrado el acceso quizás demasiado: no puede obtener el peso de un gato existente en el programa, incluso si lo necesita. Esto tampoco es una opción. Tal como está, nuestra clase es esencialmente inutilizable. Idealmente, debemos permitir algún tipo de acceso limitado:
  • Otros programadores deberían poder crear objetos Cat
  • Deben poder leer datos de objetos existentes (por ejemplo, obtener el nombre o la edad de un gato existente)
  • También debería ser posible asignar valores de campo. Pero al hacerlo, solo se deben permitir valores válidos. Nuestros objetos deben protegerse de valores inválidos (por ejemplo, edad = -1000, etc.).
¡Esa es una lista decente de requisitos! En realidad, todo esto se logra fácilmente con métodos especiales llamados getters y setters.
Getters y setters - 2
Estos nombres provienen de "get" (es decir, "método para obtener el valor de un campo") y "set" (es decir, "método para establecer el valor de un campo"). Veamos cómo se ven en nuestra clase Cat :

public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       this.weight = weight;
   }
}
Como puede ver, se ven bastante simples :) Sus nombres a menudo consisten en "get"/"set" más el nombre del campo relevante. Por ejemplo, el método getWeight() devuelve el valor del campo de peso para el objeto al que se llama. Así es como se ve en un programa:

public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       String smudgeName = smudge.getName();
       int smudgeAge = smudge.getAge();
       int smudgeWeight = smudge.getWeight();

       System.out.println("Cat's name: " + smudgeName);
       System.out.println("Cat's age: " + smudgeAge);
       System.out.println("Cat's weight: " + smudgeWeight);
   }
}
Salida de la consola:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
Ahora otra clase ( Main ) puede acceder a los campos Cat , pero solo a través de captadores. Tenga en cuenta que los captadores tienen el modificador de acceso público, es decir, están disponibles desde cualquier parte del programa. Pero, ¿qué pasa con la asignación de valores? Para esto están los métodos setter

public void setName(String name) {
   this.name = name;
}
Como puedes ver, también son simples. Llamamos al método setName() en un objeto Cat , pasamos una cadena como argumento y la cadena se asigna al campo de nombre del objeto.

public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);

       System.out.println("Cat's original name: " + smudge.getName());
       smudge.setName("Mr. Smudge");
       System.out.println("Cat's new name: " + smudge.getName());
   }
}
Aquí estamos usando getters y setters. Primero, usamos un captador para obtener y mostrar el nombre original del gato. Luego, usamos un setter para asignar un nuevo nombre ("Mr. Smudge"). Y luego usamos el captador una vez más para obtener el nombre (para verificar si realmente cambió). Salida de la consola:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
Entonces, ¿cuál es la diferencia? Todavía podemos asignar valores no válidos a los campos, incluso si tenemos setters:

public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       smudge.setAge(-1000);

       System.out.println("Smudge's age: " + smudge.getAge());
   }
}
Salida de la consola:
Smudge's age: -1000 years
La diferencia es que un colocador es un método completo. Y a diferencia de un campo, un método le permite escribir la lógica de verificación necesaria para evitar valores inaceptables. Por ejemplo, puede evitar fácilmente que se asigne un número negativo como edad:

public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age can't be negative!");
   }
}
¡Y ahora nuestro código funciona correctamente!

public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       smudge.setAge(-1000);

       System.out.println("Smudge's age: " + smudge.getAge());
   }
}
Salida de la consola:
Error! Age can't be negative!
Smudge's age: 5 years
Dentro del setter, creamos una restricción que nos protegía del intento de establecer datos no válidos. La edad de Smudge no cambió. Siempre debe crear getters y setters. Incluso si no hay restricciones sobre los valores que pueden tomar sus campos, estos métodos de ayuda no harán daño. Imagine la siguiente situación: usted y sus colegas están escribiendo un programa juntos. Creas una clase Cat con campos públicos. Todos los programadores los están usando como quieren. Y luego, un buen día, te das cuenta: "¡Mierda, tarde o temprano alguien podría asignar accidentalmente un número negativo al peso! ¡Necesitamos crear setters y hacer que todos los campos sean privados!" Haces exactamente eso e instantáneamente rompes todo el código escrito por tus colegas. Después de todo, ellosCat campos directamente.

cat.name = "Behemoth";
¡Y ahora los campos son privados y el compilador arroja un montón de errores!

cat.name = "Behemoth";//error! The Cat class's name field is private!
En este caso, sería mejor ocultar los campos y crear getters y setters desde el principio. Todos tus colegas las habrían usado. Y si tardíamente se dio cuenta de que necesitaba restringir de alguna manera los valores de campo, podría haber escrito el cheque dentro del colocador. Y el código de nadie sería descifrado. Por supuesto, si desea que el acceso a un campo sea solo de "solo lectura", puede crear solo un captador para él. Solo los métodos deben estar disponibles externamente (es decir, fuera de su clase). Los datos deben estar ocultos. Podríamos hacer una comparación con un teléfono móvil. Imagina que en lugar del habitual teléfono móvil cerrado, te dan un teléfono con una carcasa abierta, con todo tipo de cables, circuitos, etc. que sobresalen. Pero el teléfono funciona: si te esfuerzas mucho y pinchas los circuitos, incluso podrías capaz de hacer una llamada. Pero tu'
Getters y setters - 3
En cambio, el fabricante le brinda una interfaz: el usuario simplemente ingresa los dígitos correctos, presiona el botón verde de llamada y comienza la llamada. A ella no le importa lo que suceda adentro con los circuitos y cables, o cómo hacen su trabajo. En este ejemplo, la empresa limita el acceso al "interior" del teléfono (datos) y expone solo una interfaz (métodos). Como resultado, el usuario obtiene lo que quería (la capacidad de hacer una llamada) y ciertamente no romperá nada en su interior. Para reforzar lo que aprendió, le sugerimos que vea una lección en video de nuestro Curso de Java
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION