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 |
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);
| Prefix | Convention | Access |
|---|---|---|
name |
Public | Anywhere |
_name |
Protected | Class + subclasses |
__name |
Private | Class only (name mangling) |
"Bundle data and methods that operate on that data."
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;
}
}
"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)
"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)