Menu
Coddy logo textTech

Implementación de ocultamiento de datos

Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy — lección 33 de 70.

La ocultación de datos va más allá de simplemente usar campos private. Se trata de diseñar su clase de modo que los detalles de implementación interna sean completamente invisibles para el código externo, exponiendo solo lo necesario a través de una interfaz pública limpia.

Considera una clase que rastrea la contraseña de un usuario. No quieres que nadie acceda a la contraseña sin procesar, ni siquiera para leerla:

public class UserAccount
{
    private string passwordHash;
    
    public void SetPassword(string password)
    {
        passwordHash = HashPassword(password);
    }
    
    public bool VerifyPassword(string password)
    {
        return HashPassword(password) == passwordHash;
    }
    
    private string HashPassword(string password)
    {
        return password.GetHashCode().ToString();
    }
}

Observe que no hay forma de recuperar la contraseña o incluso el hash. El código externo solo puede establecer una contraseña o verificar una; el mecanismo de almacenamiento interno está completamente oculto. El método HashPassword también es privado porque es un detalle de implementación que podría cambiar sin afectar la forma en que se utiliza la clase.

Este enfoque protege su clase contra el mal uso y le otorga la libertad de cambiar los aspectos internos más adelante. Si decide utilizar un algoritmo de hashing diferente, ningún código externo se verá afectado porque nada dependía de cómo se almacenaba la contraseña.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de billetera segura que demuestre la verdadera ocultación de datos. Crearás una billetera digital donde el saldo esté completamente protegido del acceso directo: el código externo solo puede depositar, retirar y verificar si las transacciones son posibles, pero nunca ver o manipular el saldo real directamente.

Organizarás tu código en dos archivos:

  • Wallet.cs: Crea una clase Wallet en el espacio de nombres Finance que mantenga su saldo completamente oculto. La billetera debe tener:
    • Un campo privado para almacenar el saldo (decimal)
    • Un método privado FormatBalance() que devuelva el saldo formateado como una cadena de moneda como "$123.45"; este es un ayudante interno que no debe ser expuesto
    • Un método público Deposit(decimal amount) que sume al saldo solo si el monto es positivo, devolviendo true si tiene éxito, false en caso contrario
    • Un método público Withdraw(decimal amount) que reste del saldo solo si el monto es positivo y no excede el saldo actual, devolviendo true si tiene éxito, false en caso contrario
    • Un método público CanAfford(decimal amount) que devuelva true si el saldo es mayor o igual al monto, false en caso contrario
    • Un método público GetStatement() que utilice internamente el método privado FormatBalance() y devuelva "Current balance: {formatted balance}"
    ¡Nota que no hay forma de leer o establecer directamente el saldo; solo puedes interactuar con él a través de métodos controlados!
  • Program.cs: En tu archivo principal, crea una Wallet y realiza una serie de transacciones utilizando valores de entrada. Muestra cómo la billetera protege su estado interno mientras sigue proporcionando funcionalidad útil a través de su interfaz pública.

Recibirás tres entradas:

  • Monto del depósito inicial (decimal)
  • Monto del retiro a intentar (decimal)
  • Monto para verificar la asequibilidad (decimal)

Imprime la salida en este formato:

Deposit {amount}: {True/False}
{GetStatement() result}
Withdraw {amount}: {True/False}
{GetStatement() result}
Can afford {amount}: {True/False}

Por ejemplo, si las entradas son 100.50, 30.25 y 80.00, la salida debería ser:

Deposit 100.50: True
Current balance: $100.50
Withdraw 30.25: True
Current balance: $70.25
Can afford 80.00: False

La idea clave aquí es que el código externo nunca toca directamente el campo del saldo. Incluso la cadena del saldo formateada proviene de un método público que utiliza internamente un ayudante privado. ¡Esto es ocultación de datos: los detalles de implementación son completamente invisibles y eres libre de cambiar cómo se almacena o formatea el saldo sin romper ningún código que use tu billetera!

Hoja de referencia

El ocultamiento de datos significa diseñar clases de modo que los detalles de implementación interna sean completamente invisibles para el código externo, exponiendo solo lo necesario a través de una interfaz pública limpia.

Use campos private para almacenar datos sensibles y proporcione acceso controlado a través de métodos public:

public class UserAccount
{
    private string passwordHash;
    
    public void SetPassword(string password)
    {
        passwordHash = HashPassword(password);
    }
    
    public bool VerifyPassword(string password)
    {
        return HashPassword(password) == passwordHash;
    }
    
    private string HashPassword(string password)
    {
        return password.GetHashCode().ToString();
    }
}

Principios clave:

  • Sin acceso directo a los datos internos (sin getters para campos sensibles)
  • Métodos auxiliares privados para los detalles de implementación
  • Los métodos públicos solo proporcionan operaciones controladas
  • El mecanismo de almacenamiento interno está completamente oculto

Esto protege a la clase del mal uso y permite cambiar la implementación interna sin romper el código externo.

Pruébalo tú mismo

using System;
using Finance;

class Program
{
    public static void Main(string[] args)
    {
        // Leer los valores de entrada
        decimal depositAmount = Convert.ToDecimal(Console.ReadLine());
        decimal withdrawAmount = Convert.ToDecimal(Console.ReadLine());
        decimal checkAmount = Convert.ToDecimal(Console.ReadLine());

        // TODO: Crear una instancia de Wallet
        
        // TODO: Realizar el depósito e imprimir el resultado en el formato: "Deposit {amount}: {True/False}"
        
        // TODO: Imprimir el estado de cuenta usando GetStatement()
        
        // TODO: Realizar el retiro e imprimir el resultado en el formato: "Withdraw {amount}: {True/False}"
        
        // TODO: Imprimir el estado de cuenta usando GetStatement()
        
        // TODO: Verificar la asequibilidad e imprimir el resultado en el formato: "Can afford {amount}: {True/False}"
    }
}
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