🏗️ Object-Oriented Programming

OOP Fundamentals

What is Object-Oriented Programming?

OOP is a programming paradigm based on objects — data structures containing data (attributes) and code (methods). The four pillars:

Pillar Description
Encapsulation Bundle data + methods; hide internal state
Inheritance Derive new classes from existing ones
Polymorphism Same interface, different implementations
Abstraction Hide complexity, expose only essentials

Classes and Objects

Class = Blueprint (definition)
Object = Instance (concrete realization)
class Vehicle:
    def __init__(self, make: str, model: str, year: int):
        self.make = make
        self.model = model
        self.year = year
        self._speed = 0  # protected by convention

    def accelerate(self, amount: int) -> int:
        self._speed += amount
        return self._speed

# Usage
car = Vehicle("Toyota", "Camry", 2024)
car.accelerate(30)
#include <string>

class Vehicle {
private:
    std::string make_;
    std::string model_;
    int year_;
    int speed_ = 0;

public:
    Vehicle(std::string make, std::string model, int year)
        : make_(std::move(make)), model_(std::move(model)), year_(year) {}

    int accelerate(int amount) {
        speed_ += amount;
        return speed_;
    }
};

// Usage
Vehicle car("Toyota", "Camry", 2024);
car.accelerate(30);
public final class Vehicle {
    private final String make;
    private final String model;
    private final int year;
    private int speed = 0;

    public Vehicle(String make, String model, int year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    public int accelerate(int amount) {
        speed += amount;
        return speed;
    }
}

// Usage
Vehicle car = new Vehicle("Toyota", "Camry", 2024);
car.accelerate(30);
public sealed class Vehicle {
    private readonly string Make;
    private readonly string Model;
    private readonly int Year;
    private int Speed = 0;

    public Vehicle(string make, string model, int year) {
        Make = make;
        Model = model;
        Year = year;
    }

    public int Accelerate(int amount) {
        Speed += amount;
        return Speed;
    }
}

// Usage
var car = new Vehicle("Toyota", "Camry", 2024);
car.Accelerate(30);

Visibility

Prefix Convention Access
name Public Anywhere
_name Protected Class + subclasses
__name Private Class only (name mangling)

The Four Pillars in Depth

1. Encapsulation

"Bundle data and methods that operate on that data."

  • Control access via getters/setters/properties
  • Invariants maintained internally
  • Reduces coupling
class BankAccount:
    def __init__(self, initial: float = 0.0):
        self._balance = float(initial)

    @property
    def balance(self) -> float:
        return self._balance

    def deposit(self, amount: float) -> None:
        if amount > 0:
            self._balance += amount

    def withdraw(self, amount: float) -> bool:
        if 0 < amount <= self._balance:
            self._balance -= amount
            return True
        return False
#include <stdexcept>

class BankAccount {
    double balance_ = 0.0;

public:
    explicit BankAccount(double initial = 0.0) : balance_(initial) {}

    double balance() const { return balance_; }

    void deposit(double amount) {
        if (amount > 0) balance_ += amount;
        else throw std::invalid_argument("Amount must be positive");
    }

    bool withdraw(double amount) {
        if (amount > 0 && amount <= balance_) {
            balance_ -= amount;
            return true;
        }
        return false;
    }
};
public final class BankAccount {
    private double balance = 0.0;

    public BankAccount() {}
    public BankAccount(double initial) { this.balance = initial; }

    public double getBalance() { return balance; }

    public void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("Amount must be positive");
        balance += amount;
    }

    public boolean withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            return true;
        }
        return false;
    }
}
public sealed class BankAccount {
    private decimal _balance = 0m;

    public BankAccount() {}
    public BankAccount(decimal initial) => _balance = initial;

    public decimal Balance => _balance;

    public void Deposit(decimal amount) {
        if (amount <= 0) throw new ArgumentException("Amount must be positive");
        _balance += amount;
    }

    public bool Withdraw(decimal amount) {
        if (amount > 0 && amount <= _balance) {
            _balance -= amount;
            return true;
        }
        return false;
    }
}

2. Inheritance

"Derive specialized classes from general ones."

from abc import ABC, abstractmethod

class Animal(ABC):
    def __init__(self, name: str):
        self.name = name

    @abstractmethod
    def speak(self) -> str:
        pass

class Dog(Animal):
    def speak(self) -> str:
        return "Woof!"

class Cat(Animal):
    def speak(self) -> str:
        return "Meow!"

# Usage
animals = [Dog("Rex"), Cat("Whiskers")]
for animal in animals:
    print(f"{animal.name}: {animal.speak()}")
#include <string>
#include <memory>
#include <iostream>

class Animal {
protected:
    std::string name_;

public:
    explicit Animal(std::string name) : name_(std::move(name)) {}
    virtual ~Animal() = default;

    virtual std::string speak() const = 0;
    const std::string& name() const { return name_; }
};

class Dog : public Animal {
public:
    explicit Dog(std::string name) : Animal(std::move(name)) {}
    std::string speak() const override { return "Woof!"; }
};

class Cat : public Animal {
public:
    explicit Cat(std::string name) : Animal(std::move(name)) {}
    std::string speak() const override { return "Meow!"; }
};

// Usage
int main() {
    std::vector<std::unique_ptr<Animal>> animals;
    animals.push_back(std::make_unique<Dog>("Rex"));
    animals.push_back(std::make_unique<Cat>("Whiskers"));

    for (const auto& a : animals) {
        std::cout << a->speak() << '\n';
    }
}
public abstract class Animal {
    private final String name;

    protected Animal(String name) { this.name = name; }
    public String getName() { return name; }
    public abstract String speak();
}

public final class Dog extends Animal {
    public Dog(String name) { super(name); }
    @Override public String speak() { return "Woof!"; }
}

public final class Cat extends Animal {
    public Cat(String name) { super(name); }
    @Override public String speak() { return "Meow!"; }
}

// Usage
List<Animal> animals = List.of(new Dog("Rex"), new Cat("Whiskers"));
for (Animal a : animals) System.out.println(a.speak());
public abstract class Animal {
    public string Name { get; }
    protected Animal(string name) => Name = name;
    public abstract string Speak();
}

public sealed class Dog : Animal {
    public Dog(string name) : base(name) {}
    public override string Speak() => "Woof!";
}

public sealed class Cat : Animal {
    public Cat(string name) : base(name) {}
    public override string Speak() => "Meow!";
}

// Usage
var animals = new List<Animal> { new Dog("Rex"), new Cat("Whiskers") };
foreach (var a in animals) Console.WriteLine(a.Speak());

Key concepts: - super() / base() / super() — call parent method - Method overriding — same name, different behavior - Abstract base classes (abc module / abstract / virtual)

3. Polymorphism

"One interface, many implementations."

def make_sound(animal: Animal) -> None:
    print(animal.speak())

# Usage
animals = [Dog("Rex"), Cat("Whiskers")]
for animal in animals:
    make_sound(animal)  # Woof! / Meow!
void make_sound(const Animal& animal) {
    std::cout << animal.speak() << '\n';
}

int main() {
    Dog dog("Rex");
    Cat cat("Whiskers");
    make_sound(dog);  // Woof!
    make_sound(cat);  // Meow!
}
public static void makeSound(Animal animal) {
    System.out.println(animal.speak());
}

public static void main(String[] args) {
    makeSound(new Dog("Rex"));  // Woof!
    makeSound(new Cat("Whiskers"));  // Meow!
}
static void MakeSound(Animal animal) {
    Console.WriteLine(animal.Speak());
}

static void Main() {
    MakeSound(new Dog("Rex"));   // Woof!
    MakeSound(new Cat("Whiskers")); // Meow!
}

Key concepts: - super() / base() / super() — call parent method - Method overriding — same name, different behavior - Abstract base classes (abc module / abstract / virtual)