En nuestro ejemplo anterior, definimos un método ‘setName’ que establece un campo de clase ‘name’ que declaramos. Un método cuya única responsabilidad es escribir o modificar un campo de clase se conoce como «setter» o «método setter». Por el contrario, un método cuya única responsabilidad es devolver los datos actuales de un campo de clase se conoce como «captador» o «método captador».
Los contenedores como arrays tienen métodos como ‘longitud’, que son métodos de captación:
int[] arr = [ 1, 2, 3 ]; arr.length; // 3
El método de ‘longitud’ para arreglos devuelve el tamaño del arreglo, determinado por el número de elementos del arreglo. Sin embargo, es posible que haya notado una peculiaridad: no tuvimos que usar paréntesis para llamar al método ‘longitud’. Esto se debe a que la propiedad ‘longitud’ de los arreglos se define de una manera especial. Resulta que podemos definir nuestras propias clases para tener estos métodos especiales.
Comencemos redefiniendo nuestro método ‘setName’ como un método setter. Abra Cat.jspp y simplemente agregue la palabra clave ‘propiedad’ delante de ‘setName’ así:
external $; module Animals { class Cat { string name; var $element = $( """ <div class="animal"> <i class="icofont icofont-animal-cat"></i> </div> """ ); property void setName(string name) { this.name = name; } void render() { $("#content").append($element); $element.attr("title", name); } } }
En este punto, si intenta compilar, obtendrá un error (JSPPE0150). Necesitamos editar nuestro archivo main.jspp para reflejar nuestro cambio en un setter. Dado que definimos ‘setName’ como setter, ya no podemos llamarlo usando paréntesis, sino que debemos usar el operador de asignación (=) en su lugar:
import Animals; Cat cat1 = new Cat(); // cat1.setName("Kitty"); cat1.setName = "Kitty"; cat1.render(); Cat cat2 = new Cat(); // cat2.setName("Kat"); cat2.setName = "Kat"; cat2.render();
Ahora, si intenta compilar el proyecto, debería ser un éxito.
¡Eso fue bastante fácil! El único detalle que quizás queramos considerar en este punto es que el nombre es una propiedad del gato. ‘setName’ implica una acción. Dado que no podemos tener campos y métodos con nombres en conflicto, podemos cambiar el nombre de nuestro campo ‘nombre’ privado a cualquiera de las numerosas convenciones de nomenclatura: mName, _name, etc. En este tutorial, vamos a preferir el guión bajo para evitar conflictos de nombres. ya que, en algunos lenguajes dinámicos (incluidos JavaScript y Python), los guiones bajos se utilizan para «denotar» privacidad (incluso si no son realmente «privados» en la práctica). Al cambiar el nombre de nuestro campo privado ‘nombre’, esto nos libera para usar el identificador ‘nombre’ como método de configuración. Cambie el código Cat.jspp de la siguiente manera:
external $; module Animals { class Cat { string _name; var $element = $( """ <div class="animal"> <i class="icofont icofont-animal-cat"></i> </div> """ ); property void name(string name) { _name = name; } void render() { $element.attr("title", _name); $("#content").append($element); } } }
Además, cambie main.jspp para reflejar este cambio:
import Animals; Cat cat1 = new Cat(); cat1.name = "Kitty"; cat1.render(); Cat cat2 = new Cat(); cat2.name = "Kat"; cat2.render();
Los métodos setter nos permiten asignar un valor (operación de escritura). Sin embargo, si quisiéramos obtener el valor (operación de lectura), no se permitirá a menos que definamos un método getter que lo acompañe. Intente «leer» el campo ‘nombre’ así:
import Animals; Cat cat1 = new Cat(); cat1.name = "Kitty"; cat1.render(); Cat cat2 = new Cat(); cat2.name = "Kat"; cat2.name; cat2.render();
Si intenta compilar, obtendrá un error:
JSPPE0203: No getter defined for `Animals.Cat.name' at line 8 char 0 at main.jspp
Como ya habrá deducido, el parámetro para un método setter es el valor asignado a la propiedad (el valor en el lado derecho). En nuestro main.jspp anterior, los valores eran strings «Kitty» y «Kat». Naturalmente, los métodos setter solo pueden aceptar un parámetro. Dado que los captadores son una operación de «lectura», no es necesario aceptar valores; por lo tanto, los métodos getter intuitivamente no requieren parámetros. Usando esta intuición, podemos definir un método getter que lo acompañe:
external $; module Animals { class Cat { string _name; var $element = $( """ <div class="animal"> <i class="icofont icofont-animal-cat"></i> </div> """ ); property string name() { return _name; } property void name(string name) { _name = name; } void render() { $element.attr("title", _name); $("#content").append($element); } } }
Ahora, si intenta compilar el proyecto, debería poder compilar con éxito.
Como ha visto, si define un setter sin getter, puede evitar todas las operaciones de «lectura». Por el contrario, si define un getter sin un setter, puede evitar todas las operaciones de «escritura». Si define ambos, puede tener operaciones de lectura y escritura. Esto le permite personalizar a sus necesidades.