Handbooks / OOP & Design Patterns / Chapter 1
The Four Pillars of OOP
7 pages · ~5 min✓ Reviewed
Start here. Next up: SOLID Principles.
Classes and Objects: The Mental Model
1. Class vs Object
- Class = blueprint: state (fields) + behavior (methods)
- Object = one instance, created at runtime
- Constructor runs on creation to initialise state
- No constructor defined → compiler adds a no-arg default
| Instance field | static member | |
|---|---|---|
| Belongs to | one object | the class |
| Copies | one per object | one, shared |
2. Example: Create and Call
Car c = new Car("red");
c.drive();one object, method called through the reference c
3. Gotcha: Reference ≠ Object
Car a = new Car("red"); Car b = a; b.color = "blue"; // a.color is now "blue"
b = acopies the reference, not the object- Both point to the same object
A variable holds a reference. Change through either name and both see it.
Encapsulation and Abstraction
1. Encapsulation
- Encapsulation = data plus the methods that act on it, in one class
- Fields are private; outside code uses public methods
- Getters/setters validate input and let internals change without breaking callers
private double balance;
public void deposit(double x) {
if (x <= 0)
throw new IllegalArgumentException();
balance += x;
}balance can never get a bad value
2. Abstraction vs Encapsulation
- Abstraction = expose what an object does, hide how
- Built with
abstract classandinterface - Model only the essential behavior
| Encapsulation | Abstraction | |
|---|---|---|
| Goal | Protect state | Simplify the design |
| Idea | Information hiding | Essential behavior only |
| Tool | private fields | abstract classes, interfaces |
3. Common Mistake
- Public getter returning the internal mutable list leaks state
Return List.copyOf(items) or Collections.unmodifiableList(items), never the raw list.
Inheritance and the super Keyword
1. What Inheritance Is
- Inheritance = subclass reuses and extends a superclass
- Models is-a: a Dog is an Animal
- Syntax:
class Dog extends Animal - Subclass gets the non-private fields and methods
2. super and Single Inheritance
super(...)calls the parent constructor: first statement in the child constructorsuper.method()calls the parent version of a method- Java allows one superclass only
- Multiple behavior: implement several interfaces
class Dog extends Animal { Dog() { super("Rex"); } void speak() { super.speak(); } }
parent constructor first, then parent method
3. Abstract Class vs Interface
| Abstract class | Interface | |
|---|---|---|
| State | fields + constructors | no instance state |
| Purpose | shared base for related classes | contract for unrelated classes |
| Inherit | extends one | implements many |
final class cannot be extended; final method cannot be overridden.
Polymorphism: Overloading vs Overriding
1. One Interface, Many Forms
- Polymorphism = one call, behaviour depends on the object
- Overloading: same name, different parameters, same class; compile time (static binding)
- Overriding: subclass redefines inherited method, same signature; runtime (dynamic dispatch)
2. Example: Runtime Type Wins
class Animal { void speak() { print("..."); } } class Dog extends Animal { @Override void speak() { print("Woof"); } } Animal a = new Dog(); a.speak();
runtime type decides, not the reference type
Woof
3. Overloading vs Overriding
| Overloading | Overriding | |
|---|---|---|
| Where | same class | subclass |
| Signature | different parameters | same signature |
| Bound | compile time | runtime |
| Return type | alone cannot overload | same or covariant |
| Access | any | no narrower than parent |
4. Gotchas
staticmethods are hidden, not overriddenprivateandfinalmethods cannot be overridden
A typo in the name or parameters becomes a compile error, not a silent new method.
Composition vs Inheritance
1. Has-a vs Is-a
- Composition = has-a: a field holds another object
- Work is delegated to it (Car has an Engine)
| Inheritance | Composition | |
|---|---|---|
| Relation | is-a | has-a |
| Coupling | tight, compile-time | loose |
| Swap at runtime | no | yes |
2. Example: Car has an Engine
- Engine is passed in;
start()delegates to it
class Car {
private Engine engine;
Car(Engine e) { this.engine = e; }
void start() { engine.start(); }
}3. Choosing and Mistakes
- Inheriting only to reuse code: fragile base class, a parent change breaks every child
- Deep hierarchies are hard to follow: keep them shallow
Type the field as an interface so the part can be swapped at runtime.
OOP Cheat Sheet
1. Classes and Pillars
| Idea | Remember |
|---|---|
| Class | blueprint; object = one instance |
static | shared by the class |
| Instance | one copy per object |
| Encapsulation | private fields + public methods |
| Abstraction | expose what, hide how |
2. Inheritance and Polymorphism
- Inheritance = is-a,
extends,super() - Reference type decides what you can call
- Object type decides which override runs
| Overriding | Overloading | |
|---|---|---|
| Signature | same in the child | same name, different parameters |
| Resolved | runtime | compile time |
Animal a = new Dog(); a.speak(); // Dog.speak() runs a.fetch(); // compile error
Animal has no fetch()
3. Choosing
extendsfor is-a, composition for has-a- Default to composition
- Use
@Overrideandfinaldeliberately
The reference type sets what you can call; the object type sets which override runs.
Check yourself
Animal a = new Dog(); a.speak(); a.fetch(); Dog overrides speak and adds fetch. What happens?
a.speak()runs Dog's version: the object type picks the overridea.fetch()fails to compile: the reference type Animal has no fetch
After Car b = a; b.color = "blue";, what does a.color hold?
blue:b = acopies the reference, not the object- Both names point at one Car
A getter does return items; for a private list. Why is that still a leak?
- Callers get the real list, so
getItems().clear()empties your state - Return
List.copyOf(items)or an unmodifiable view
Can int f(int x) overload void f(int x) in one class?
- No: the parameter lists match, only the return type differs
- Overloads need different parameters