OOP Notes
Learn how getter and setter methods provide controlled access to private fields — with validation, computed properties, and best practices.
// With getter/setter — FULL control public class Player { private int health; private int maxHealth;
public Player(int maxHealth) { this.maxHealth = maxHealth; this.health = maxHealth; }
public int getHealth() { return health; }
public void setHealth(int health) { // Validation: health stays in valid range if (health < 0) this.health = 0; else if (health > maxHealth) this.health = maxHealth; else this.health = health; }
public void takeDamage(int damage) { setHealth(this.health - damage); // Reuses validation logic }
public boolean isAlive() { return health > 0; } }
public class Product { private String name; private double price; private int quantity; private String category;
public Product(String name, double price, int quantity) { setName(name); // Use setters in constructors for validation setPrice(price); setQuantity(quantity); }
// Getter — simple read access public String getName() { return name; }
// Setter — with validation public void setName(String name) { if (name == null || name.trim().isEmpty()) { throw new IllegalArgumentException("Product name cannot be empty"); } this.name = name.trim(); }
public double getPrice() { return price; }
public void setPrice(double price) { if (price < 0) { throw new IllegalArgumentException("Price cannot be negative"); } this.price = Math.round(price * 100.0) / 100.0; // Round to 2 decimals }
public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { if (quantity < 0) { throw new IllegalArgumentException("Quantity cannot be negative"); } this.quantity = quantity; }
// Computed property — getter with no corresponding field public double getTotalValue() { return price * quantity; }
// Boolean getter uses 'is' prefix public boolean isInStock() { return quantity > 0; } }
class Circle: def __init__(self, radius): self.radius = radius # This calls the setter!
@property def radius(self): """Getter for radius""" return self._radius
@radius.setter def radius(self, value): """Setter with validation""" if value <= 0: raise ValueError("Radius must be positive") self._radius = value
@property def diameter(self): """Computed property — read-only""" return self._radius * 2
@property def area(self): """Computed property — always up to date""" return 3.14159 * self._radius ** 2
@property def circumference(self): return 2 * 3.14159 * self._radius
c = Circle(5) print(c.radius) # 5 (calls getter) print(c.area) # 78.54 (computed) c.radius = 10 # Calls setter — validates! print(c.area) # 314.16 (auto-updated)
c.radius = -3 # ValueError: Radius must be positive
c.area = 100 # AttributeError: can't set (no setter defined)
#include <iostream> #include <string> #include <stdexcept>
class BankAccount { private: std::string owner; double balance; bool frozen;
public: BankAccount(const std::string& owner, double initialBalance) : owner(owner), frozen(false) { setBalance(initialBalance); }
// Getter — const means it won't modify the object std::string getOwner() const { return owner; }
double getBalance() const { return balance; }
bool isFrozen() const { return frozen; }
// Setter with validation and business logic void setBalance(double amount) { if (amount < 0) { throw std::invalid_argument("Balance cannot be negative"); } balance = amount; }
void freeze() { frozen = true; std::cout << "Account frozen for " << owner << std::endl; }
void deposit(double amount) { if (frozen) throw std::runtime_error("Account is frozen"); if (amount <= 0) throw std::invalid_argument("Must deposit positive amount"); balance += amount; } };
public class Order { private String orderId; // Getter ONLY — IDs never change private LocalDateTime created; // Getter ONLY — creation time is fixed private String status; // Getter + controlled mutation via methods private List<Item> items; // Getter (copy) + add/remove methods
// Read-only — no setter provided public String getOrderId() { return orderId; } public LocalDateTime getCreated() { return created; }
// Status changes through business methods, not a raw setter public String getStatus() { return status; }
public void confirm() { if (!"PENDING".equals(status)) throw new IllegalStateException(); this.status = "CONFIRMED"; }
public void ship() { if (!"CONFIRMED".equals(status)) throw new IllegalStateException(); this.status = "SHIPPED"; }
// No setItems() — controlled add/remove instead public void addItem(Item item) { items.add(item); } public void removeItem(Item item) { items.remove(item); } public List<Item> getItems() { return Collections.unmodifiableList(items); } }
// BAD — this is just a public field with extra steps private int x; public int getX() { return x; } public void setX(int x) { this.x = x; } // No validation = pointless
// BAD — allows inconsistent state public void setStartDate(Date start) { this.start = start; } public void setEndDate(Date end) { this.end = end; } // Someone could set end before start!
// GOOD — maintains invariant public void setDateRange(Date start, Date end) { if (end.before(start)) throw new IllegalArgumentException(); this.start = start; this.end = end; }
## Common Mistakes
1. **Blindly generating getters/setters for all fields** — only expose what's needed
2. **No validation in setters** — the whole point is to validate!
3. **Setters for immutable values** — IDs, creation timestamps shouldn't have setters
4. **Returning mutable objects from getters** — return copies instead
5. **Using setters when business methods are better** — `order.ship()` is clearer than `order.setStatus("shipped")`
## Key Takeaways
- Getters **read** values; setters **write** values with validation
- Not every field needs both — think about what should be mutable vs. read-only
- **Validation** in setters prevents invalid object states
- **Computed properties** (like `area` from `radius`) are getters without stored fields
- Prefer **business methods** (`ship()`, `activate()`) over raw setters for state transitions
- Python's `@property` provides getter/setter behavior with clean attribute-access syntaxExam Focus
Revise definitions, diagrams, examples, and short-answer points for Getters and Setters.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Object Oriented Programming (OOP) topic.
Search Terms
object-oriented-programming, object oriented programming (oop), object, oriented, programming, encapsulation, getters, and
Related Object Oriented Programming (OOP) Topics