Encapsulation
Protecting Your Data Like a Bank Vault
Keeping Your Data Safe
In previous lessons, we learned about classes, data, methods, and constructors. Now let's learn how to protect your data using Encapsulation!
- Encapsulation = Keeping your data private and safe
- Like a bank vault - you can only access it through proper channels
- Like a car - you use the steering wheel, not the engine directly
Why is encapsulation important? It protects your data from being changed incorrectly. It makes your code safer, easier to maintain, and more professional.
Step 1: What is Encapsulation?
Encapsulation means hiding the internal details of a class and only showing what's necessary.
Without Encapsulation (BAD)
public class Person
{
public int Age; // Anyone can change this!
}
// ❌ Problem: Anyone can set bad data
Person p = new Person();
p.Age = -5; // This is wrong but allowed!
With Encapsulation (GOOD)
public class Person
{
private int age; // ✅ Hidden!
public int Age // ✅ Controlled access
{
get { return age; }
set
{
if (value > 0 && value < 120)
age = value;
}
}
}
Step 2: Access Modifiers - Who Can See What?
Access modifiers control who can see and use different parts of your class.
public
✅ Anyone can see it
public string Name;
private
✅ Only this class can see it
private string password;
protected
✅ Class and children can see it
protected string baseData;
Step 3: Private Fields - The Data Storage
Private fields store your data safely where nobody else can touch them.
Private Fields Example
public class Student
{
// ✅ Private - only this class can see
private string name;
private int age;
private double gpa;
// ✅ Public - everyone can see
public string StudentId;
}
Why Use Private Fields?
- ✅ Protection - Nobody can change your data directly
- ✅ Safety - Prevents bad data from getting in
- ✅ Control - You decide how data is accessed
// ❌ Cannot access private fields
Student s = new Student();
// s.name = "John"; // ERROR! Private!
// ✅ Can access public fields
s.StudentId = "S123"; // Works!
Step 4: Public Properties - The Controlled Door
Public properties are like a door with a security guard - they control access to your private data.
Property with Validation
public class Product
{
private decimal price; // Hidden data
// Public property with validation
public decimal Price
{
get { return price; }
set
{
if (value >= 0) // ✅ Check!
price = value;
}
}
}
Using Properties
Product p = new Product();
// ✅ Property validates the data
p.Price = 25.50m; // Works!
p.Price = -10.00m; // ❌ Ignored (price stays 25.50)
Console.WriteLine(p.Price); // 25.50
- ✅ Validation - Check data before saving
- ✅ Protection - Keep data safe
- ✅ Flexibility - Change how data works later
Step 5: Different Access Levels
You can control who can read and who can write each property.
Read-Only
Everyone can read, only the class can change
public class BankAccount
{
private decimal balance;
// ✅ Everyone can read the balance
public decimal Balance
{
get { return balance; }
private set { balance = value; } // Only class can change
}
}
Init-Only (C# 9+)
Set only when created, never change again
public class Person
{
// ✅ Can be set when created
public int Id { get; init; }
public string Name { get; set; }
}
// Usage
Person p = new Person { Id = 1, Name = "John" };
// p.Id = 2; // ❌ ERROR! Cannot change after creation
Step 6: Private Methods - Internal Helpers
Private methods are helper methods that only your class can use.
Private Method Example
public class Calculator
{
// ✅ Public - everyone can use
public int Add(int a, int b)
{
return InternalAdd(a, b); // Calls private method
}
// ✅ Private - only this class can use
private int InternalAdd(int a, int b)
{
return a + b + 1; // Internal logic
}
}
Why Private Methods?
- ✅ Hide complexity - Keep internal logic hidden
- ✅ Organize code - Break big tasks into small parts
- ✅ Reuse - Use the same helper in multiple places
CalculateDiscount() method that only the class needs to use.
Real-World Example: Employee Management
Let's build a complete Employee class with encapsulation:
Employee.cs
using System;
public class Employee
{
// ✅ Private fields - hidden data
private string name;
private decimal salary;
private int yearsOfService;
// ✅ Public properties - controlled access
public string Name
{
get { return name; }
set
{
if (!string.IsNullOrWhiteSpace(value))
name = value;
}
}
public decimal Salary
{
get { return salary; }
private set // ✅ Only class can change salary
{
if (value >= 0) salary = value;
}
}
public int YearsOfService
{
get { return yearsOfService; }
private set { yearsOfService = value; }
}
// ✅ Read-only property
public string EmployeeLevel
{
get
{
if (yearsOfService < 2) return "Junior";
if (yearsOfService < 5) return "Mid";
return "Senior";
}
}
// Constructor
public Employee(string name, decimal salary, int years)
{
Name = name;
Salary = salary;
YearsOfService = years;
}
// ✅ Public methods - what the employee can do
public void GiveRaise(decimal percentage)
{
if (percentage > 0)
Salary += Salary * (percentage / 100);
}
public void DisplayInfo()
{
Console.WriteLine($"Name: {Name}");
Console.WriteLine($"Salary: ${Salary}");
Console.WriteLine($"Level: {EmployeeLevel}");
}
}
Program.cs
using System;
class Program
{
static void Main()
{
// Create employee
Employee emp = new Employee("John Doe", 50000.00m, 3);
// ✅ Can read public data
Console.WriteLine($"Name: {emp.Name}");
Console.WriteLine($"Level: {emp.EmployeeLevel}");
// ✅ Can change through public methods
emp.GiveRaise(10); // 10% raise
emp.DisplayInfo();
// ❌ Cannot access private data directly
// emp.salary = 60000; // ERROR! Private
// emp.yearsOfService = 5; // ERROR! Private
}
}
- ✅ Private fields - Data is hidden and safe
- ✅ Public properties - Controlled access with validation
- ✅ Private setters - Only the class can change certain data
- ✅ Read-only properties - Calculate values when needed
- ✅ Public methods - Safe ways to change data
What You Learned Today
Encapsulation
Protecting your data
Private
Hidden data & methods
Public
Controlled access
Validation
Keep data correct
Exercise: Create a Course Class
Your Task:
Create a Course class with proper encapsulation:
Requirements:
-
Private fields:
courseName(string)maxStudents(int)currentStudents(int)
-
Public properties:
CourseName- cannot be emptyMaxStudents- must be 1-50CurrentStudents- read-onlySeatsAvailable- read-only (calculated)
More Requirements:
-
Public methods:
AddStudent()- increases currentStudentsRemoveStudent()- decreases currentStudentsDisplayInfo()- shows course details
-
Validation:
- Can't add more than MaxStudents
- Can't remove if no students
// Course.cs
using System;
public class Course
{
// Private fields
private string courseName;
private int maxStudents;
private int currentStudents;
// Public properties with validation
public string CourseName
{
get { return courseName; }
set
{
if (!string.IsNullOrWhiteSpace(value))
courseName = value;
}
}
public int MaxStudents
{
get { return maxStudents; }
set
{
if (value >= 1 && value <= 50)
maxStudents = value;
}
}
public int CurrentStudents
{
get { return currentStudents; }
private set { currentStudents = value; } // ✅ Only class can change
}
// ✅ Read-only property
public int SeatsAvailable => MaxStudents - CurrentStudents;
// Constructor
public Course(string name, int max)
{
CourseName = name;
MaxStudents = max;
CurrentStudents = 0;
}
// Public methods
public void AddStudent()
{
if (CurrentStudents >= MaxStudents)
{
Console.WriteLine("❌ Course is full!");
return;
}
CurrentStudents++;
Console.WriteLine($"✅ Student added. {SeatsAvailable} seats left.");
}
public void RemoveStudent()
{
if (CurrentStudents <= 0)
{
Console.WriteLine("❌ No students to remove!");
return;
}
CurrentStudents--;
Console.WriteLine($"❌ Student removed. {SeatsAvailable} seats left.");
}
public void DisplayInfo()
{
Console.WriteLine($"📚 Course: {CourseName}");
Console.WriteLine($" Students: {CurrentStudents}/{MaxStudents}");
Console.WriteLine($" Seats Available: {SeatsAvailable}");
}
}
// Program.cs
class Program
{
static void Main()
{
Course course = new Course("C# Programming", 3);
course.AddStudent(); // ✅ Added
course.AddStudent(); // ✅ Added
course.AddStudent(); // ✅ Added
course.AddStudent(); // ❌ Course is full!
course.DisplayInfo();
course.RemoveStudent(); // ✅ Removed
course.RemoveStudent(); // ✅ Removed
course.RemoveStudent(); // ✅ Removed
course.RemoveStudent(); // ❌ No students!
}
}