Data Hiding Implementation
Part of the Object Oriented Programming section of Coddy's C# journey — lesson 33 of 70.
Data hiding goes beyond just using private fields. It's about designing your class so that internal implementation details are completely invisible to outside code, exposing only what's necessary through a clean public interface.
Consider a class that tracks a user's password. You don't want anyone accessing the raw password - not even to read it:
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();
}
}Notice there's no way to retrieve the password or even the hash. External code can only set a password or verify one - the internal storage mechanism is completely hidden. The HashPassword method is also private because it's an implementation detail that could change without affecting how the class is used.
This approach protects your class from misuse and gives you freedom to change internals later. If you decide to use a different hashing algorithm, no external code breaks because nothing depended on how the password was stored.
Challenge
EasyLet's build a secure wallet system that demonstrates true data hiding. You'll create a digital wallet where the balance is completely protected from direct access - external code can only deposit, withdraw, and check if transactions are possible, but never see or manipulate the actual balance directly.
You'll organize your code across two files:
Wallet.cs: Create aWalletclass in theFinancenamespace that keeps its balance completely hidden. The wallet should have:- A private field to store the balance (decimal)
- A private method
FormatBalance()that returns the balance formatted as a currency string like"$123.45"- this is an internal helper that shouldn't be exposed - A public method
Deposit(decimal amount)that adds to the balance only if the amount is positive, returningtrueif successful,falseotherwise - A public method
Withdraw(decimal amount)that subtracts from the balance only if the amount is positive and doesn't exceed the current balance, returningtrueif successful,falseotherwise - A public method
CanAfford(decimal amount)that returnstrueif the balance is greater than or equal to the amount,falseotherwise - A public method
GetStatement()that uses the privateFormatBalance()method internally and returns"Current balance: {formatted balance}"
Program.cs: In your main file, create aWalletand perform a series of transactions using input values. Show how the wallet protects its internal state while still providing useful functionality through its public interface.
You will receive three inputs:
- Initial deposit amount (decimal)
- Withdrawal amount to attempt (decimal)
- Amount to check affordability for (decimal)
Print the output in this format:
Deposit {amount}: {True/False}
{GetStatement() result}
Withdraw {amount}: {True/False}
{GetStatement() result}
Can afford {amount}: {True/False}For example, if the inputs are 100.50, 30.25, and 80.00, the output should be:
Deposit 100.50: True
Current balance: $100.50
Withdraw 30.25: True
Current balance: $70.25
Can afford 80.00: FalseThe key insight here is that external code never directly touches the balance field. Even the formatted balance string comes through a public method that internally uses a private helper. This is data hiding - the implementation details are completely invisible, and you're free to change how the balance is stored or formatted without breaking any code that uses your wallet!
Cheat sheet
Data hiding means designing classes so internal implementation details are completely invisible to outside code, exposing only what's necessary through a clean public interface.
Use private fields to store sensitive data and provide controlled access through public methods:
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();
}
}Key principles:
- No direct access to internal data (no getters for sensitive fields)
- Private helper methods for implementation details
- Public methods provide controlled operations only
- Internal storage mechanism is completely hidden
This protects the class from misuse and allows changing internal implementation without breaking external code.
Try it yourself
using System;
using Finance;
class Program
{
public static void Main(string[] args)
{
// Read input values
decimal depositAmount = Convert.ToDecimal(Console.ReadLine());
decimal withdrawAmount = Convert.ToDecimal(Console.ReadLine());
decimal checkAmount = Convert.ToDecimal(Console.ReadLine());
// TODO: Create a Wallet instance
// TODO: Perform deposit and print result in format: "Deposit {amount}: {True/False}"
// TODO: Print the statement using GetStatement()
// TODO: Perform withdrawal and print result in format: "Withdraw {amount}: {True/False}"
// TODO: Print the statement using GetStatement()
// TODO: Check affordability and print result in format: "Can afford {amount}: {True/False}"
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesNamespaces & DirectivesIntro to Classes & ObjectsThe 'this' KeywordMethods and ParametersFields vs PropertiesConstructorsObject InitializersRecap - Simple Calculator4Inheritance
Basic Inheritance (:) SyntaxThe 'base' KeywordVirtual & Override KeywordsSealed ClassesThe 'object' Base ClassRecap - Employee Hierarchy7Advanced Features
Operator OverloadingIndexers (this[])ToString() OverrideExtension MethodsRecap - Custom List2Properties & Static Members
Auto-Implemented PropertiesRead/Write-Only PropertiesStatic Fields & MethodsStatic ClassesExpression-Bodied Members5Polymorphism & Interfaces
Compile vs Runtime PolyInterface vs Abstract ClassMultiple InterfacesExplicit InterfacesUpcasting & DowncastingRecap - Shape Calculator3Class Architecture
Instance vs Static Data'readonly' & 'const' KeywordsBacking FieldsRecap - Bank Account Manager6Encapsulation
Access ModifiersProperties for EncapsulationData Hiding ImplementationImmutability PatternsRecap - Student Records