How to learn OOP Basics
Object-oriented design groups state with the operations that keep that state valid. A class is useful when it protects an invariant or gives a domain idea a clear name; creating getters, setters, and inheritance for every noun is not a design goal by itself.
Begin with one small class and one responsibility. Decide what must be true after construction, keep fields private when callers should not change them freely, and expose behavior that describes intent. This makes the object easier to test and harder to misuse.
Recommended learning order
- Classes and instances: Define fields and methods, create objects with new, and understand that each instance has its own state while static members belong to the class.
- Construct valid objects: Use constructors to require essential values. Reject invalid inputs at the boundary instead of allowing a half-valid object.
- Encapsulate behavior: Keep representation details private and add methods that perform valid state transitions, such as deposit rather than setBalance.
- Use polymorphism deliberately: After composition and simple classes are clear, study interfaces and overriding. Depend on the smallest useful contract.
Tested example: Protect a class invariant
The constructor prevents a negative opening balance, and deposit is the only public way to increase it. Callers can observe the balance but cannot assign an arbitrary value.
public class Main {
static final class Account {
private int balance;
Account(int openingBalance) {
if (openingBalance < 0) throw new IllegalArgumentException("negative balance");
balance = openingBalance;
}
void deposit(int amount) {
if (amount <= 0) throw new IllegalArgumentException("deposit must be positive");
balance += amount;
}
int balance() { return balance; }
}
public static void main(String[] args) {
Account account = new Account(100);
account.deposit(25);
System.out.println(account.balance());
}
}Expected output
125Common mistakes
- Making every field public, which lets callers bypass validation and break object invariants.
- Adding setters mechanically even when a value should never change after construction.
- Confusing an object reference with the object itself; two variables can refer to the same mutable instance.
- Using static fields for per-object state, causing all instances to share a value accidentally.
How to practice
Build classes before class hierarchies. After each exercise, describe the invariant in one sentence and check whether any public method can break it. Then continue to the inheritance hub to study substitutable types and interfaces.
Exercises to do first
- Create a class — Define state and behavior for one small domain object.
- Constructor — Require essential values when the object is created.
- Getters and setters — Expose only the access that the class contract genuinely needs.