Encapsulation
Keep the data private and let the outside world change it only through methods that enforce the rules.
Watch it animatedStep through it, with the running line highlighted. Free with an account.The idea
If any code could write to balance, any code could break it. Making the field private means every change goes through Withdraw, so the rule "never overdraw" lives in exactly one place.
Code
class Account {
double balance_ = 500; // hidden from outside
public:
double balance() const { return balance_; } // read-only view
void withdraw(double amount) {
if (amount <= 0 || amount > balance_)
throw invalid_argument("Invalid amount");
balance_ -= amount;
}
};class Account:
def __init__(self):
self._balance = 500 # "private" by convention
@property
def balance(self) -> float: # read-only view
return self._balance
def withdraw(self, amount: float) -> None:
if amount <= 0 or amount > self._balance:
raise ValueError("Invalid amount")
self._balance -= amountclass Account {
private decimal balance = 500; // hidden from outside
public decimal Balance => balance; // read-only view
public void Withdraw(decimal amount) {
if (amount <= 0 || amount > balance)
throw new InvalidOperationException("Invalid amount");
balance -= amount;
}
}Tips
- Try 100, 800 and -50 as the second amount.
- Expose the least you can. It is easy to make something public later and very hard to take it back.
In the .NET library
Auto-properties do this in one line: public decimal Balance { get; private set; }. Use init instead of set for values that are fixed after construction.