Lección 3 · 3 de 20
Getters, setters y miembros privados · Dart
Proteja el estado de sus clases en Dart con miembros privados (_), getters calculados y setters que validan, con una cuenta bancaria de ejemplo.

En Dart no existen las palabras private ni public: un nombre que empieza por guion bajo (_balanceCents, _history) es privado de la biblioteca, es decir, del archivo donde está. Desde otro archivo no se puede leer ni escribir; dentro del mismo archivo, sí. Por eso la privacidad se nota sobre todo cuando el proyecto crece en varios archivos y cada clase vive en el suyo.
Los getters (get) se leen como un campo, sin paréntesis, pero calculan su valor cada vez. balance devuelve el saldo con formato y history devuelve una copia no modificable con List.unmodifiable, de modo que nadie de fuera pueda cambiar la lista interna: el intento account.history.add('fake') lanza UnsupportedError, que el programa captura.
Un setter (set) se usa como una asignación, account.dailyLimit = 20000, pero ejecuta código: aquí comprueba que el límite no sea negativo y anota el cambio en el historial. Con -1 lanza ArgumentError y el valor anterior se conserva. Tener getter y setter con el mismo nombre hace que, visto desde fuera, dailyLimit parezca un campo normal.
En main aparece el operador de cascada ..: BankAccount('Lucia')..deposit(12000)..deposit(3550) llama a dos métodos sobre el mismo objeto y el resultado de toda la expresión es la cuenta, no lo que devuelva deposit. Es muy habitual para configurar un objeto recién creado.
Código · main.dart
class BankAccount { final String owner; // A leading _ makes a name private to this file (its library). int _balanceCents = 0; int _dailyLimit = 50000; final List<String> _history = []; BankAccount(this.owner); // Getters read like fields but are computed on demand. String get balance => '${(_balanceCents / 100).toStringAsFixed(2)} EUR'; List<String> get history => List.unmodifiable(_history); int get dailyLimit => _dailyLimit; // A setter looks like an assignment, but can validate. set dailyLimit(int cents) { if (cents < 0) throw ArgumentError('limit cannot be negative'); _dailyLimit = cents; _history.add('limit $cents'); } void deposit(int cents) { _balanceCents += cents; _history.add('deposit $cents'); }}void main() { final account = BankAccount('Lucia')..deposit(12000)..deposit(3550); account.dailyLimit = 20000; // calls the setter print('${account.owner}: ${account.balance}, limit ${account.dailyLimit}'); try { account.dailyLimit = -1; } on ArgumentError catch (e) { print('Rejected: ${e.message}'); } try { account.history.add('fake'); } on UnsupportedError { print('Read-only: ${account.history}'); }}Salida · dart run main.dart
Lucia: 155.50 EUR, limit 20000 Rejected: limit cannot be negative Read-only: [deposit 12000, deposit 3550, limit 20000]
Para recordar
_nombrees privado del archivo (la biblioteca), no de la clase.- Un getter se lee como un campo y se calcula al pedirlo.
- Un setter se usa con
=y permite validar el valor. - Devuelva copias no modificables de sus listas internas.
..encadena llamadas sobre el mismo objeto.
Ejercicio
Añada un método withdraw(int cents) que lance StateError si la retirada supera el saldo o el límite diario, y pruebe a retirar 30000 céntimos.