Menu
Coddy logo textTech

Miembros públicos vs. privados

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 30 de 110.

El encapsulamiento es uno de los principios fundamentales de la programación orientada a objetos. Se trata de controlar el acceso a los datos internos de una clase, decidiendo qué debe ser visible para el mundo exterior y qué debe permanecer oculto.

En Dart, los miembros de clase (campos y métodos) son públicos por defecto. Esto significa que cualquier código puede acceder a ellos directamente:

class BankAccount {
  String owner;
  double balance;
  
  BankAccount(this.owner, this.balance);
}

var account = BankAccount('Alice', 1000);
account.balance = -500;  // ¡Cualquiera puede modificar esto directamente!

Esto es problemático. Nada impide establecer un saldo no válido.

Para proteger los datos internos, Dart utiliza miembros privados. Un miembro se vuelve privado cuando su nombre comienza con un guion bajo _:

class BankAccount {
  String owner;
  double _balance;  // Privado - comienza con guion bajo
  
  BankAccount(this.owner, this._balance);
  
  double get balance => _balance;  // Acceso controlado
}

Ahora no se puede acceder directamente a _balance desde fuera de la librería donde se define la clase. El código externo debe usar el getter público en su lugar. Esto te permite controlar cómo se leen y modifican los datos, asegurando que tus objetos siempre permanezcan en un estado válido.

challenge icon

Desafío

Fácil

Vamos a construir un gestor de contraseñas sencillo que demuestre la diferencia entre los miembros públicos y privados. Verás cómo el prefijo de guion bajo protege los datos sensibles de ser accedidos directamente desde fuera de la librería de la clase.

Crearás dos archivos para organizar tu código:

  • credential.dart: Define una clase Credential que almacene información de inicio de sesión para un sitio web. La clase debe tener:
    • Un String website público: no hay problema en que cualquiera vea para qué sitio web es esto
    • Un String username público: el nombre de usuario puede ser visible
    • Un String _password privado: la contraseña real debe estar protegida
    • Un constructor que reciba los tres valores
    • Un getter público password que devuelva el _password privado (acceso controlado)
    • Un método getMaskedPassword() que devuelva la contraseña con todos los caracteres reemplazados por asteriscos * (de la misma longitud que la contraseña real)
    • Un método displayCredential() que imprima la información de la credencial de forma segura (mostrando la contraseña enmascarada, no la real)
  • main.dart: Importa tu clase de credenciales y demuestra cómo la encapsulación protege la contraseña:
    • Crea una credencial para el sitio web 'github.com', usuario 'dev_user' y contraseña 'secret123'
    • Crea otra credencial para el sitio web 'email.com', usuario 'john_doe' y contraseña 'myP@ss'
    • Para cada credencial, llama a displayCredential(), luego imprime Actual password length: [length] usando el getter público para acceder a la longitud de la contraseña

El método displayCredential() debe imprimir en este formato:

--- Credential ---
Website: [website]
Username: [username]
Password: [maskedPassword]

Salida esperada:

--- Credential ---
Website: github.com
Username: dev_user
Password: *********
Actual password length: 9
--- Credential ---
Website: email.com
Username: john_doe
Password: ******
Actual password length: 6

Hoja de referencia

El encapsulamiento controla el acceso a los datos internos de una clase al decidir qué debe ser visible y qué debe permanecer oculto.

En Dart, los miembros de la clase son públicos por defecto:

class BankAccount {
  String owner;
  double balance;  // Público - se puede acceder directamente
  
  BankAccount(this.owner, this.balance);
}

var account = BankAccount('Alice', 1000);
account.balance = -500;  // Se permite la modificación directa

Para proteger los datos internos, use miembros privados anteponiendo un guion bajo _ al nombre:

class BankAccount {
  String owner;
  double _balance;  // Privado - comienza con un guion bajo
  
  BankAccount(this.owner, this._balance);
  
  double get balance => _balance;  // Acceso controlado a través de un getter
}

No se puede acceder directamente a los miembros privados desde fuera de la librería donde se define la clase. Utilice getters y métodos públicos para proporcionar un acceso controlado a los datos privados, asegurando que los objetos permanezcan en un estado válido.

Pruébalo tú mismo

import 'credential.dart';

void main() {
  // TODO: Crea una credencial para github.com
  // website: 'github.com', username: 'dev_user', password: 'secret123'
  
  // TODO: Llama a displayCredential() en la primera credencial
  
  // TODO: Imprime la longitud real de la contraseña usando el getter público
  // Formato: "Actual password length: [length]"
  
  // TODO: Crea una credencial para email.com
  // website: 'email.com', username: 'john_doe', password: 'myP@ss'
  
  // TODO: Llama a displayCredential() en la segunda credencial
  
  // TODO: Imprime la longitud real de la contraseña usando el getter público
}
quiz iconPonte a prueba

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