Menu
Coddy logo textTech

Implementação de Ocultação de Dados

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 33 de 70.

A ocultação de dados vai além de apenas usar campos private. Trata-se de projetar sua classe de modo que os detalhes de implementação interna sejam completamente invisíveis para o código externo, expondo apenas o que é necessário por meio de uma interface pública limpa.

Considere uma classe que rastreia a senha de um usuário. Você não quer que ninguém acesse a senha bruta - nem mesmo para lê-la:

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 não há como recuperar a senha ou mesmo o hash. O código externo só pode definir uma senha ou verificar uma - o mecanismo de armazenamento interno está completamente oculto. O método HashPassword também é privado porque é um detalhe de implementação que pode mudar sem afetar como a classe é usada.

Essa abordagem protege sua classe contra o uso indevido e oferece a liberdade de alterar os componentes internos posteriormente. Se você decidir usar um algoritmo de hashing diferente, nenhum código externo será quebrado, pois nada dependia de como a senha era armazenada.

challenge icon

Desafio

Fácil

Vamos construir um sistema de carteira segura que demonstra a verdadeira ocultação de dados. Você criará uma carteira digital onde o saldo é completamente protegido contra acesso direto - o código externo só pode depositar, sacar e verificar se as transações são possíveis, mas nunca ver ou manipular o saldo real diretamente.

Você organizará seu código em dois arquivos:

  • Wallet.cs: Crie uma classe Wallet no namespace Finance que mantém seu saldo completamente oculto. A carteira deve ter:
    • Um campo privado para armazenar o saldo (decimal)
    • Um método privado FormatBalance() que retorna o saldo formatado como uma string de moeda como "$123.45" - este é um auxiliar interno que não deve ser exposto
    • Um método público Deposit(decimal amount) que adiciona ao saldo apenas se o valor for positivo, retornando true se for bem-sucedido, false caso contrário
    • Um método público Withdraw(decimal amount) que subtrai do saldo apenas se o valor for positivo e não exceder o saldo atual, retornando true se for bem-sucedido, false caso contrário
    • Um método público CanAfford(decimal amount) que retorna true se o saldo for maior ou igual ao valor, false caso contrário
    • Um método público GetStatement() que usa o método privado FormatBalance() internamente e retorna "Current balance: {formatted balance}"
    Observe que não há como ler ou definir o saldo diretamente - você só pode interagir com ele por meio de métodos controlados!
  • Program.cs: No seu arquivo principal, crie uma Wallet e realize uma série de transações usando valores de entrada. Mostre como a carteira protege seu estado interno enquanto ainda fornece funcionalidade útil por meio de sua interface pública.

Você receberá três entradas:

  • Valor do depósito inicial (decimal)
  • Valor do saque a tentar (decimal)
  • Valor para verificar a capacidade de pagamento (decimal)

Imprima a saída neste formato:

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

Por exemplo, se as entradas forem 100.50, 30.25 e 80.00, a saída deve ser:

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

A ideia principal aqui é que o código externo nunca toca diretamente no campo de saldo. Mesmo a string de saldo formatada vem através de um método público que usa internamente um auxiliar privado. Isso é ocultação de dados - os detalhes da implementação são completamente invisíveis, e você está livre para alterar como o saldo é armazenado ou formatado sem quebrar nenhum código que use sua carteira!

Folha de consulta

O ocultamento de dados significa projetar classes de modo que os detalhes da implementação interna fiquem completamente invisíveis para o código externo, expondo apenas o que é necessário por meio de uma interface pública limpa.

Use campos private para armazenar dados sensíveis e fornecer acesso controlado por meio 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();
    }
}

Princípios fundamentais:

  • Sem acesso direto aos dados internos (sem getters para campos sensíveis)
  • Métodos auxiliares privados para detalhes de implementação
  • Métodos públicos fornecem apenas operações controladas
  • O mecanismo de armazenamento interno é completamente oculto

Isso protege a classe contra o uso indevido e permite alterar a implementação interna sem quebrar o código externo.

Experimente você mesmo

using System;
using Finance;

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

        // TODO: Criar uma instância de Wallet
        
        // TODO: Realizar o depósito e imprimir o resultado no formato: "Deposit {amount}: {True/False}"
        
        // TODO: Imprimir o extrato usando GetStatement()
        
        // TODO: Realizar o saque e imprimir o resultado no formato: "Withdraw {amount}: {True/False}"
        
        // TODO: Imprimir o extrato usando GetStatement()
        
        // TODO: Verificar a acessibilidade financeira e imprimir o resultado no formato: "Can afford {amount}: {True/False}"
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos