La convención del prefijo _
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 31 de 110.
El prefijo de guion bajo _ es la forma en que Dart marca los miembros como privados. A diferencia de los lenguajes que utilizan palabras clave como private, Dart se basa en esta convención de nomenclatura para controlar la visibilidad.
Puedes aplicar el guion bajo tanto a campos como a métodos:
class Counter {
int _count = 0; // Campo privado
void _increment() { // Método privado
_count++;
}
void increase() { // Método público
_increment();
print('Count: $_count');
}
}El guion bajo funciona para cualquier identificador: variables, métodos, getters, setters e incluso nombres de clases. Una clase llamada _Helper sería privada para su biblioteca.
class Person {
String _name; // Privado
int _age; // Privado
Person(this._name, this._age);
String get name => _name; // Getter público
void _validateAge(int age) { } // Método privado
}Dentro de la misma clase, accedes a los miembros privados con normalidad. La restricción solo se aplica al código fuera de la librería. Esta convención deja claro de inmediato al leer el código qué miembros están destinados únicamente para uso interno: cualquier cosa que comience con _ es un detalle de implementación.
Desafío
FácilVamos a construir un rastreador de puntuación para un juego que demuestre cómo el prefijo de guion bajo mantiene ocultos los detalles de implementación interna mientras expone una interfaz pública limpia.
Organizarás tu código en dos archivos:
score_tracker.dart: Crea una claseScoreTrackerque gestione la puntuación de un jugador con la encapsulación adecuada. La clase debe tener:- Un
String playerNamepúblico: todos pueden ver quién está jugando - Un
int _scoreprivado inicializado en0: la puntuación bruta debe estar protegida - Un
int _bonusMultiplierprivado inicializado en1: esta es una mecánica interna del juego - Un constructor que reciba el nombre del jugador
- Un getter público
scoreque devuelva el_scoreprivado - Un método privado
_applyBonus(int points)que devuelvapoints * _bonusMultiplier - Un método público
addPoints(int points)que use_applyBonusinternamente para calcular los puntos reales añadidos, actualice_scoree imprimaAdded [calculated] points! - Un método público
activateDoubleBonus()que establezca_bonusMultiplieren2e imprimaDouble bonus activated! - Un método público
displayStats()que muestre el estado actual del jugador
- Un
main.dart: Importa tu rastreador de puntuación y simula una sesión de juego:- Crea un
ScoreTrackerpara el jugador'Alex' - Llama a
displayStats() - Añade
10puntos - Añade
25puntos - Activa el bono doble
- Añade
15puntos (esto debería duplicarse) - Llama a
displayStats() - Imprime
Final score: [score]usando el getter público
- Crea un
El método displayStats() debe imprimir en este formato:
=== Player Stats ===
Player: [playerName]
Current Score: [_score]Observa cómo el método privado _applyBonus y el campo _bonusMultiplier manejan el cálculo del bono internamente. El código externo solo ve los métodos públicos y no tiene idea del sistema de multiplicadores; ese es un detalle de implementación oculto tras la convención del guion bajo.
Salida esperada:
=== Player Stats ===
Player: Alex
Current Score: 0
Added 10 points!
Added 25 points!
Double bonus activated!
Added 30 points!
=== Player Stats ===
Player: Alex
Current Score: 65
Final score: 65Hoja de referencia
El prefijo de guion bajo _ marca los miembros como privados en Dart. Esta convención de nomenclatura controla la visibilidad sin usar palabras clave como private.
Aplica el guion bajo a campos y métodos:
class Counter {
int _count = 0; // Campo privado
void _increment() { // Método privado
_count++;
}
void increase() { // Método público
_increment();
print('Count: $_count');
}
}El guion bajo funciona para cualquier identificador: variables, métodos, getters, setters y nombres de clases:
class Person {
String _name; // Privado
int _age; // Privado
Person(this._name, this._age);
String get name => _name; // Getter público
void _validateAge(int age) { } // Método privado
}Los miembros privados son accesibles dentro de la misma clase, pero están restringidos para el código fuera de la librería. Cualquier cosa que comience con _ es un detalle de implementación.
Pruébalo tú mismo
import 'score_tracker.dart';
void main() {
// TODO: Crear un ScoreTracker para el jugador 'Alex'
// TODO: Llamar a displayStats()
// TODO: Añadir 10 puntos
// TODO: Añadir 25 puntos
// TODO: Activar el bono doble
// TODO: Añadir 15 puntos (esto debería duplicarse)
// TODO: Llamar a displayStats()
// TODO: Imprimir 'Final score: [score]' usando el getter público
}
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