OOP Concepts in Java - Encapsulation, Inheritance, Polymorphism | Java Codeex

1. What is OOP?

Object-Oriented Programming (OOP) is a programming paradigm that organises software design around data (objects) rather than functions and logic. Java is fundamentally an object-oriented language — almost everything in Java is an object.

OOP is built on four core pillars:

Pillar One-Line Definition Key Java Construct
Encapsulation Bundling data and methods; hiding internal details private fields + getters/setters
Inheritance A class acquires properties of another class extends
Polymorphism One interface, many forms Overloading & @Override
Abstraction Hiding complexity, exposing only essentials abstract class / interface

Why OOP? OOP promotes code reusability, modularity, maintainability, and makes it easier to model real-world entities in software.

2. Classes and Objects

A class is a blueprint or template that defines the state (fields) and behaviour (methods) that objects of its type will have. An object is a concrete instance of a class, created using the new keyword.

// Class = blueprint
public class Car {
    // Fields (state)
    String brand;
    String model;
    int year;
    double speed;

    // Method (behaviour)
    public void accelerate(double amount) {
        speed += amount;
        System.out.println(brand + " is now going at " + speed + " km/h");
    }

    public void brake(double amount) {
        speed = Math.max(0, speed - amount);
        System.out.println(brand + " slowed down to " + speed + " km/h");
    }

    public void displayInfo() {
        System.out.println(year + " " + brand + " " + model);
    }
}

// Main class to use the Car object
public class Main {
    public static void main(String[] args) {
        // Creating objects (instances) of Car
        Car car1 = new Car();   // object 1
        car1.brand = "Toyota";
        car1.model = "Corolla";
        car1.year = 2022;

        Car car2 = new Car();   // object 2
        car2.brand = "Honda";
        car2.model = "Civic";
        car2.year = 2023;

        car1.displayInfo();     // 2022 Toyota Corolla
        car1.accelerate(60);    // Toyota is now going at 60.0 km/h
        car2.displayInfo();     // 2023 Honda Civic
    }
}
2022 Toyota Corolla
Toyota is now going at 60.0 km/h
2023 Honda Civic

Memory: Each object gets its own copy of instance fields but shares class-level (static) fields and methods.

3. Constructors

A constructor is a special method that is automatically called when an object is created with new. It has the same name as the class and no return type.

Default Constructor

If you do not define any constructor, Java provides a no-argument default constructor automatically. Once you define any constructor, the default is no longer provided.

Parameterized Constructor

public class Car {
    String brand;
    String model;
    int year;

    // Default constructor
    public Car() {
        brand = "Unknown";
        model = "Unknown";
        year = 0;
    }

    // Parameterized constructor
    public Car(String brand, String model, int year) {
        this.brand = brand;   // 'this' distinguishes field from parameter
        this.model = model;
        this.year  = year;
    }

    // Copy constructor
    public Car(Car other) {
        this.brand = other.brand;
        this.model = other.model;
        this.year  = other.year;
    }

    // Constructor chaining with this()
    public Car(String brand) {
        this(brand, "Generic", 2024);  // calls parameterized constructor
    }

    public void display() {
        System.out.println(year + " " + brand + " " + model);
    }
}

public class Main {
    public static void main(String[] args) {
        Car c1 = new Car();                        // default
        Car c2 = new Car("Ford", "Mustang", 2023); // parameterized
        Car c3 = new Car(c2);                      // copy
        Car c4 = new Car("BMW");                   // chained

        c1.display();  // 0 Unknown Unknown
        c2.display();  // 2023 Ford Mustang
        c3.display();  // 2023 Ford Mustang
        c4.display();  // 2024 BMW Generic
    }
}
0 Unknown Unknown
2023 Ford Mustang
2023 Ford Mustang
2024 BMW Generic

Note: this() must be the first statement in a constructor. You cannot call both this() and super() in the same constructor.

4. The this Keyword

this is a reference to the current object — the object whose method or constructor is being called. It has three main uses:

public class Person {
    String name;
    int age;

    // Use 1: Disambiguate fields from parameters
    public Person(String name, int age) {
        this.name = name;  // 'this.name' = field, 'name' = parameter
        this.age  = age;
    }

    // Use 2: Call another constructor (constructor chaining)
    public Person(String name) {
        this(name, 0);     // delegates to Person(String, int)
    }

    // Use 3: Pass current object as argument
    public void register(Registry r) {
        r.add(this);       // passes the current Person object
    }

    public String getInfo() {
        return this.name + ", age " + this.age;
    }
}

class Registry {
    public void add(Person p) {
        System.out.println("Registered: " + p.getInfo());
    }
}

public class Main {
    public static void main(String[] args) {
        Person p = new Person("Alice", 30);
        System.out.println(p.getInfo());   // Alice, age 30

        Registry reg = new Registry();
        p.register(reg);                   // Registered: Alice, age 30
    }
}