Unit 3 · OOP Concepts

3.4.1Getters, setters and validation

How to encapsulate a class

  1. Make all attributes private.
  2. Provide getters (accessors) to read values.
  3. Provide setters (mutators) to change values, with validation.
Java
public class BankAccount {
    private String accountNo;
    private double balance;

    public BankAccount(String accountNo, double openingBalance) {
        this.accountNo = accountNo;
        setBalance(openingBalance);
    }

    // getters
    public String getAccountNo() { return accountNo; }
    public double getBalance()   { return balance; }

    // setter with validation
    public void setBalance(double balance) {
        if (balance >= 0) {
            this.balance = balance;
        } else {
            System.out.println("Balance cannot be negative");
        }
    }

    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        } else {
            System.out.println("Invalid or insufficient");
        }
    }
}

Naming: getX() and setX(); for boolean values, isX().

No setAccountNo() method is provided, so the account number is read-only. Encapsulation lets you make an attribute read-only, write-only or validated.

Reading the BankAccount class

Ways to handle an invalid value

The example prints a message and keeps the old value. That is easy to understand, but the calling code never finds out that something went wrong. Larger programs usually either return a result that reports success, or throw an exception that the caller must deal with:

Java
public boolean withdraw(double amount) {        // report success
    if (amount <= 0 || amount > balance) return false;
    balance -= amount;
    return true;
}

public void setMarks(int marks) {               // refuse with an exception
    if (marks < 0 || marks > 100)
        throw new IllegalArgumentException("Marks must be 0 to 100");
    this.marks = marks;
}

Benefits

Encapsulation and data hiding

These two terms are often used as if they meant the same thing, but there is a small difference. Data hiding is making the data private. Encapsulation is the bigger idea: keeping the data and the methods that work on it together in one class, and allowing access only through those methods. Data hiding is the tool; encapsulation is the design.

Making an immutable class

An object whose state can never change after it is created is called immutable. To make one: make every attribute private final, set them all in the constructor, provide getters only, and mark the class final so no subclass can add setters.

Java
public final class Point {
    private final int x, y;
    public Point(int x, int y) { this.x = x; this.y = y; }
    public int getX() { return x; }
    public int getY() { return y; }
}

Immutable objects are simple and safe to share, because nobody can change them. String is the best-known immutable class in Java: methods such as toUpperCase() return a new String and never change the original.

Common mistake: writing a getter that returns a private list or array directly, such as return books;. The caller receives a reference to your private list and can add or remove items without going through your methods. Return a copy instead, for example return new ArrayList<>(books);, or a read-only view.

Remember

  • Private attributes, public methods, and validation inside the methods.
  • Write each rule once and reuse it, as the constructor above does by calling the setter.
  • No setter means read-only; private final and no setter means it can never change.