Introduction
Encapsulation is one of the four fundamental principles of object-oriented programming (OOP). It refers to the bundling of data (fields or properties) and methods (functions) that operate on the data into a single unit, typically a class. Encapsulation restricts direct access to some of an object’s components, which can help prevent the accidental modification of data.
Encapsulation is achieved by using access modifiers to define the accessibility of class members. It promotes modularity and code reuse, and it helps to protect the integrity of the data.
How Encapsulation Works
Encapsulation in C# is implemented using:
- Access Modifiers:
public
,private
,protected
,internal
,protected internal
, andprivate protected
. - Properties: To provide controlled access to private fields.
- Methods: To operate on the data encapsulated within the object.
Example of Encapsulation
Let’s consider a simple example where we encapsulate the details of a Person
class.
using System;
namespace EncapsulationExample
{
public class Person
{
// Private fields
private string name;
private int age;
// Public properties to access and modify private fields
public string Name
{
get { return name; }
set
{
if (!string.IsNullOrEmpty(value))
{
name = value;
}
else
{
throw new ArgumentException("Name cannot be null or empty");
}
}
}
public int Age
{
get { return age; }
set
{
if (value > 0)
{
age = value;
}
else
{
throw new ArgumentException("Age must be greater than zero");
}
}
}
// Constructor
public Person(string name, int age)
{
Name = name;
Age = age;
}
// Method to display person details
public void DisplayInfo()
{
Console.WriteLine($"Name: {Name}, Age: {Age}");
}
}
class Program
{
static void Main(string[] args)
{
// Creating an object of the Person class
Person person = new Person("Alice", 30);
// Accessing properties
Console.WriteLine("Person Name: " + person.Name);
Console.WriteLine("Person Age: " + person.Age);
// Modifying properties
person.Age = 35;
Console.WriteLine("Updated Person Age: " + person.Age);
// Display person details using method
person.DisplayInfo();
}
}
}
Output
Person Name: Alice
Person Age: 30
Updated Person Age: 35
Name: Alice, Age: 35
Explanation
- Private Fields: The
name
andage
fields are declared as private, which means they cannot be accessed directly from outside the class. - Public Properties: The
Name
andAge
properties provide controlled access to the private fields. They include validation logic to ensure the integrity of the data. - Constructor: The constructor initializes the private fields through the properties, ensuring that any validation logic is applied.
- Methods: The
DisplayInfo
method provides a way to output the encapsulated data.
Benefits of Encapsulation
- Data Protection: By restricting direct access to fields, encapsulation helps protect the integrity of the data.
- Modularity: Encapsulation promotes modularity by keeping related data and methods together in one class.
- Code Maintenance: Encapsulated code is easier to maintain and modify because changes to the internal implementation do not affect external code.
- Code Reusability: Encapsulation allows classes to be reused without exposing their internal implementation details.
Real-World Example
Consider a banking application where you need to encapsulate the details of a bank account.
using System;
namespace BankingExample
{
public class BankAccount
{
// Private fields
private string accountNumber;
private double balance;
// Public properties to access and modify private fields
public string AccountNumber
{
get { return accountNumber; }
}
public double Balance
{
get { return balance; }
private set { balance = value; }
}
// Constructor
public BankAccount(string accountNumber, double initialBalance)
{
this.accountNumber = accountNumber;
Balance = initialBalance;
}
// Method to deposit money
public void Deposit(double amount)
{
if (amount > 0)
{
Balance += amount;
}
else
{
throw new ArgumentException("Deposit amount must be positive");
}
}
// Method to withdraw money
public void Withdraw(double amount)
{
if (amount > 0 && amount <= Balance)
{
Balance -= amount;
}
else
{
throw new ArgumentException("Invalid withdrawal amount");
}
}
// Method to display account details
public void DisplayAccountInfo()
{
Console.WriteLine($"Account Number: {AccountNumber}, Balance: {Balance}");
}
}
class Program
{
static void Main(string[] args)
{
// Creating an object of the BankAccount class
BankAccount account = new BankAccount("1234567890", 1000);
// Displaying account information
account.DisplayAccountInfo();
// Depositing money
account.Deposit(500);
Console.WriteLine("After depositing 500:");
account.DisplayAccountInfo();
// Withdrawing money
account.Withdraw(300);
Console.WriteLine("After withdrawing 300:");
account.DisplayAccountInfo();
}
}
}
Output
Account Number: 1234567890, Balance: 1000
After depositing 500:
Account Number: 1234567890, Balance: 1500
After withdrawing 300:
Account Number: 1234567890, Balance: 1200
Explanation
- Private Fields: The
accountNumber
andbalance
fields are private to prevent direct access from outside the class. - Public Properties: The
AccountNumber
property provides read-only access to theaccountNumber
field, and theBalance
property provides read-only access to thebalance
field (with the setter being private). - Methods: The
Deposit
andWithdraw
methods provide controlled ways to modify thebalance
field, ensuring that the operations are valid.
Conclusion
Encapsulation is a key principle in OOP that helps protect the internal state of an object and ensures that it is modified only in a controlled manner. By using access modifiers, properties, and methods, you can achieve encapsulation in C# and build robust, maintainable, and reusable code.