Encapsulation and Abstraction
Hiding internal details so objects protect their own state and expose only what callers need
A class isn't truly useful just because it bundles data and methods. Its real value comes from the fact that outside code can't mess with the data directly — only the methods of the class itself can.
That discipline goes by two related names:
- Encapsulation — keep the data and the rules that govern it in one place; let no one else touch the data directly.
- Abstraction — expose only what callers need to know; hide the rest.
They are two angles on the same idea: separating "what" from "how."
A class that's badly encapsulated
Nothing about the class prevents an outside caller from setting the
balance to nonsense. The "rules of being a bank account" don't live
inside the class — they're scattered across every place that
touches Balance. That's the problem encapsulation solves.
Access modifiers: the basic tools
C# gives you a few keywords to control who can see what.
| Modifier | Visible to |
|---|---|
public | Everyone |
private | Only the class itself |
protected | The class and its subclasses |
internal | Code in the same assembly (project) |
protected internal | Subclasses or same-assembly code |
private protected | Subclasses in the same assembly |
For now, focus on private for state, public for behavior.
The properly encapsulated version
Now the only way the balance can change is by calling Deposit
or Withdraw, and those methods enforce the invariants. The class
owns its rules.
Encapsulation as a picture
The public surface is small and intentional. The internal data is locked behind it.
Abstraction: hide the how
Where encapsulation is about access, abstraction is about ignorance — a good kind of ignorance. Callers should be able to use your class without knowing how it works.
Consider a TemperatureSensor:
Callers never need to know there's a voltage involved, or that the
calibration formula could change. If we later swap the sensor model,
the Celsius and Fahrenheit properties keep working — the API is
stable even when the internals shift.
That stability is the practical payoff of abstraction.
Encapsulation vs abstraction, at a glance
| Encapsulation | Abstraction |
|---|---|
| About access to state | About what callers see |
| "Don't let anyone touch the variable" | "Don't make anyone learn how it works" |
Enforced by private, properties, methods | Enforced by API design |
| Tactic | Strategy |
They work together. Encapsulation makes abstraction safe; abstraction makes encapsulation useful.
A larger example: a Wallet
A wallet has cash inside, but no one should be able to reach in and edit the cash directly. They have to ask the wallet to do something.
Notice the invariants the class guarantees:
Cash >= 0always — it's impossible to construct or transition into a negative balance.AddandSpendonly accept positive amounts.
These guarantees are local to Wallet.cs. You can audit them by
reading one file.
Practice
Build a Counter class with:
- A read-only property
Value(int). - A constructor that takes an int starting value. If the starting value is negative, throw an
ArgumentException. - An
Increment()method that adds 1 toValue. - A
Reset()method that setsValueback to 0.
The outside world must NOT be able to set Value directly.
Program.cs runs a few operations and should print exactly:
0
3
0
caught
Test your understanding
What is the main benefit of encapsulation?
It makes the code faster
It reduces the number of lines of code
It localizes the rules that govern a piece of data, so the rest of the program can't accidentally violate them
It makes classes immutable
Which best captures "abstraction"?
A class with no fields
Hiding how something works behind a stable interface that says what it does
Making all members public
Replacing classes with structs