Getters y Setters
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 21 de 110.
Los getters y setters proporcionan una forma de acceder y modificar los campos de una clase a través de métodos especiales que parecen propiedades regulares. En lugar de exponer los campos directamente, puedes controlar cómo se leen y escriben los valores.
Un getter se define utilizando la palabra clave get y devuelve un valor calculado o almacenado:
class Rectangle {
double width;
double height;
Rectangle(this.width, this.height);
double get area => width * height;
double get perimeter => 2 * (width + height);
}
Rectangle rect = Rectangle(5, 3);
print(rect.area); // 15.0
print(rect.perimeter); // 16.0Observa que area y perimeter se acceden como campos, pero se calculan cada vez. No se necesitan paréntesis.
Un setter utiliza la palabra clave set y te permite controlar cómo se asigna un valor:
class Temperature {
double _celsius;
Temperature(this._celsius);
double get celsius => _celsius;
set celsius(double value) {
if (value >= -273.15) {
_celsius = value;
}
}
double get fahrenheit => _celsius * 9 / 5 + 32;
set fahrenheit(double value) {
celsius = (value - 32) * 5 / 9;
}
}
Temperature temp = Temperature(25);
print(temp.fahrenheit); // 77.0
temp.fahrenheit = 100;
print(temp.celsius); // 37.78El setter valida la entrada antes de almacenarla e incluso puede convertir entre unidades. Esto te da control sobre tus datos mientras mantienes una sintaxis limpia, similar a una propiedad, para los usuarios de tu clase.
Desafío
FácilVamos a construir un rastreador de puntuación para un juego que utiliza getters y setters para gestionar las estadísticas del jugador con validación y valores calculados.
Organizarás tu código en dos archivos:
player.dart: Define una clasePlayerque rastree el rendimiento de un jugador en el juego. Tu clase debe tener:- Un campo
String namepara el nombre del jugador - Un campo privado
int _scoreque comience en0 - Un campo privado
int _livesque comience en3 - Un constructor que reciba el nombre del jugador
- Un getter
scoreque devuelva la puntuación actual - Un setter
scoreque solo acepte valores de0o superiores (ignora los valores negativos) - Un getter
livesque devuelva las vidas actuales - Un setter
livesque solo acepte valores entre0y5inclusive (ignora los valores fuera de este rango) - Un getter
levelque calcule el nivel del jugador basándose en la puntuación: la puntuación dividida por100(división entera), más1 - Un getter
isAliveque devuelvatruesi las vidas son mayores que0 - Un método
displayStatus()que imprima el estado actual del jugador
- Un campo
main.dart: Importa tu clase de jugador y demuestra el funcionamiento de los getters y setters:- Crea un jugador llamado
'Alex' - Establece la puntuación en
250y llama adisplayStatus() - Intenta establecer la puntuación en
-50(debe ser ignorado) y llama adisplayStatus() - Establece las vidas en
1y llama adisplayStatus() - Intenta establecer las vidas en
10(debe ser ignorado) y llama adisplayStatus()
- Crea un jugador llamado
El método displayStatus() debe imprimir exactamente en este formato:
[name] | Score: [score] | Level: [level] | Lives: [lives] | Alive: [isAlive]Salida esperada:
Alex | Score: 250 | Level: 3 | Lives: 3 | Alive: true
Alex | Score: 250 | Level: 3 | Lives: 3 | Alive: true
Alex | Score: 250 | Level: 3 | Lives: 1 | Alive: true
Alex | Score: 250 | Level: 3 | Lives: 1 | Alive: trueHoja de referencia
Los getters y setters proporcionan un acceso controlado a los campos de la clase a través de métodos especiales que parecen propiedades normales.
Getter - definido mediante la palabra clave get, devuelve un valor calculado o almacenado:
class Rectangle {
double width;
double height;
Rectangle(this.width, this.height);
double get area => width * height;
double get perimeter => 2 * (width + height);
}
Rectangle rect = Rectangle(5, 3);
print(rect.area); // 15.0 - se accede como un campo, sin paréntesis
print(rect.perimeter); // 16.0Setter - utiliza la palabra clave set, controla cómo se asignan los valores:
class Temperature {
double _celsius;
Temperature(this._celsius);
double get celsius => _celsius;
set celsius(double value) {
if (value >= -273.15) {
_celsius = value;
}
}
double get fahrenheit => _celsius * 9 / 5 + 32;
set fahrenheit(double value) {
celsius = (value - 32) * 5 / 9;
}
}
Temperature temp = Temperature(25);
print(temp.fahrenheit); // 77.0
temp.fahrenheit = 100;
print(temp.celsius); // 37.78Los setters pueden validar la entrada y convertir entre unidades mientras mantienen una sintaxis limpia, similar a la de una propiedad.
Pruébalo tú mismo
import 'player.dart';
void main() {
// TODO: Crea un jugador llamado 'Alex'
// TODO: Establece el score a 250 y llama a displayStatus()
// TODO: Intenta establecer el score a -50 (debería ser ignorado) y llama a displayStatus()
// TODO: Establece lives a 1 y llama a displayStatus()
// TODO: Intenta establecer lives a 10 (debería ser ignorado) y llama a displayStatus()
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de POO
Archivos externosLibrerías e importacionesIntroducción a la POOClases vs. ObjetosLa palabra clave thisMétodosVariables de instanciaConceptos básicos de constructoresResumen - Calculadora sencilla4Seguridad de nulos
Introducción a la seguridad de nulosNulables vs No nulablesLos operadores ? y !Palabra clave Late y Null SafetyOperadores Null-awareNull Safety en clasesResumen - Sistema de perfil de usuario7Clases abstractas e interfaces
Clases abstractasMétodos abstractosInterfaces en DartInterfaces implícitasImplementar vs. ExtenderInterfaces múltiplesRepaso - Calculadora de figuras10Colecciones y Genéricos
Visión general de List, Set y MapColecciones con seguridad de tiposClases genéricasMétodos genéricosRestricciones genéricasIterable e IteratorResumen - Almacenamiento genérico2Constructores en Dart
Constructor por defectoConstructores nombradosListas de inicializaciónConstructores constantesConstructores de fábricaConstructores de redireccionamientoResumen - Constructor de formas5Encapsulamiento
Miembros públicos vs. privadosLa convención del prefijo _Privacidad a nivel de libreríaProfundidad en Getters y SettersOcultamiento de informaciónResumen - Registros de estudiantes8Mixins
Introducción a los MixinsCreación de MixinsUso de múltiples MixinsPalabra clave on en MixinsMixin vs HerenciaMixin vs InterfazResumen - Sistema Animal11Métodos especiales
Sobrescritura de toString()Sobrescritura de hashCode y ==Interfaz ComparableMétodo call()Sobrescritura de noSuchMethodResumen - Colección personalizada14Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy3Propiedades de clase
Miembros de instancia vs. estáticosCampos Final y ConstVariables LateMétodos y campos estáticosGetters y SettersResumen - Gestor de cuentas bancarias6Herencia
Herencia básicaLa palabra clave superSobrescritura de métodosLa anotación @overrideLa palabra clave final en clasesConstructores y herenciaResumen - Jerarquía de empleados9Polimorfismo
Fundamentos del polimorfismoPolimorfismo mediante interfacesComprobación de tipos en tiempo de ejecuciónLos operadores is y asPalabra clave covariantResumen - Procesador de pagos12POO Asíncrona
Futures y async/awaitFundamentos de StreamsStream ControllersConstructores asíncronosAsincronía en métodos de claseRepaso - Data Fetcher15Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository