"One interface, many implementations."
from abc import ABC, abstractmethod
from math import pi
class Shape(ABC):
@abstractmethod
def area(self) -> float:
pass
class Circle(Shape):
def __init__(self, radius: float):
self.radius = radius
def area(self) -> float:
return pi * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width: float, height: float):
self.width = width
self.height = height
def area(self) -> float:
return self.width * self.height
class Triangle(Shape):
def __init__(self, base: float, height: float):
self.base = base
self.height = height
def area(self) -> float:
return 0.5 * self.base * self.height
def process(shape: Shape) -> None:
print(f"Area: {shape.area():.2f}")
process(Circle(5)) # 78.54
process(Rectangle(3, 4)) # 12
process(Triangle(3, 4)) # 6
#include <iostream>
#include <cmath>
class Shape {
public:
virtual ~Shape() = default;
virtual double area() const = 0;
};
class Circle : public Shape {
double radius_;
public:
explicit Circle(double r) : radius_(r) {}
double area() const override { return M_PI * radius_ * radius_; }
};
class Rectangle : public Shape {
double width_, height_;
public:
Rectangle(double w, double h) : width_(w), height_(h) {}
double area() const override { return width_ * height_; }
};
class Triangle : public Shape {
double base_, height_;
public:
Triangle(double b, double h) : base_(b), height_(h) {}
double area() const override { return 0.5 * base_ * height_; }
};
void process(const Shape& shape) {
std::cout << "Area: " << shape.area() << std::endl;
}
int main() {
process(Circle(5)); // 78.54
process(Rectangle(3, 4)); // 12
process(Triangle(3, 4)); // 6
}
public abstract class Shape {
public abstract double area();
}
public final class Circle extends Shape {
private final double radius;
public Circle(double r) { this.radius = r; }
public double area() { return Math.PI * radius * radius; }
}
public final class Rectangle extends Shape {
private final double width, height;
public Rectangle(double w, double h) { this.width = w; this.height = h; }
public double area() { return width * height; }
}
public final class Triangle extends Shape {
private final double base, height;
public Triangle(double b, double h) { this.base = b; this.height = h; }
public double area() { return 0.5 * base * height; }
}
public final class Example {
public static void process(Shape shape) {
System.out.println("Area: " + shape.area());
}
public static void main(String[] args) {
process(new Circle(5)); // 78.54
process(new Rectangle(3, 4)); // 12
process(new Triangle(3, 4)); // 6
}
}
using System;
public abstract class Shape {
public abstract double Area();
}
public sealed class Circle : Shape {
private readonly double _radius;
public Circle(double r) => _radius = r;
public override double Area() => Math.PI * _radius * _radius;
}
public sealed class Rectangle : Shape {
private readonly double _width, _height;
public Rectangle(double w, double h) { _width = w; _height = h; }
public override double Area() => _width * _height;
}
public sealed class Triangle : Shape {
private readonly double _base, _height;
public Triangle(double b, double h) { _base = b; _height = h; }
public override double Area() => 0.5 * _base * _height;
}
public static class Program {
static void Process(Shape shape) {
Console.WriteLine($"Area: {shape.Area():F2}");
}
static void Main() {
Process(new Circle(5)); // 78.54
Process(new Rectangle(3, 4)); // 12
Process(new Triangle(3, 4)); // 6
}
}
| Type | Example |
|---|---|
| Subtype (Runtime) | Inheritance + method overriding |
| Parametric (Generics) | List[T], Optional[T] |
| Ad-hoc (Overloading) | Multiple add(a, b) for different types |
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
@abstractmethod
def charge(self, amount: float) -> bool:
pass
class StripeProcessor(PaymentProcessor):
def charge(self, amount: float) -> bool:
print(f"Charging ${amount:.2f} via Stripe")
return True
class PayPalProcessor(PaymentProcessor):
def charge(self, amount: float) -> bool:
print(f"Charging ${amount:.2f} via PayPal")
return True
class CryptoProcessor(PaymentProcessor):
def charge(self, amount: float) -> bool:
print(f"Charging ${amount:.2f} via Crypto")
return True
class PaymentProcessor {
public:
virtual bool charge(double amount) = 0;
virtual ~PaymentProcessor() = default;
};
class StripeProcessor : public PaymentProcessor {
public:
bool charge(double amount) override {
std::cout << "Charging $" << amount << " via Stripe" << std::endl;
return true;
}
};
class PayPalProcessor : public PaymentProcessor {
public:
bool charge(double amount) override {
std::cout << "Charging $" << amount << " via PayPal" << std::endl;
return true;
}
};
class CryptoProcessor : public PaymentProcessor {
public:
bool charge(double amount) override {
std::cout << "Charging $" << amount << " via Crypto" << std::endl;
return true;
}
};
public interface PaymentProcessor {
boolean charge(double amount);
}
public final class StripeProcessor implements PaymentProcessor {
public boolean charge(double amount) {
System.out.println("Charging $" + amount + " via Stripe");
return true;
}
}
public final class PayPalProcessor implements PaymentProcessor {
public boolean charge(double amount) {
System.out.println("Charging $" + amount + " via PayPal");
return true;
}
}
public final class CryptoProcessor implements PaymentProcessor {
public boolean charge(double amount) {
System.out.println("Charging $" + amount + " via Crypto");
return true;
}
}
public interface IPaymentProcessor {
bool Charge(double amount);
}
public sealed class StripeProcessor : IPaymentProcessor {
public bool Charge(double amount) {
Console.WriteLine($"Charging ${amount:F2} via Stripe");
return true;
}
}
public sealed class PayPalProcessor : IPaymentProcessor {
public bool Charge(double amount) {
Console.WriteLine($"Charging ${amount:F2} via PayPal");
return true;
}
}
public sealed class CryptoProcessor : IPaymentProcessor {
public bool Charge(double amount) {
Console.WriteLine($"Charging ${amount:F2} via Crypto");
return true;
}
}
def checkout(processor: PaymentProcessor, amount: float) -> None:
if processor.charge(amount):
print("Payment successful!")
if __name__ == "__main__":
checkout(StripeProcessor(), 99.99)
checkout(PayPalProcessor(), 49.99)
checkout(CryptoProcessor(), 199.00)
void checkout(PaymentProcessor& processor, double amount) {
if (processor.charge(amount)) {
std::cout << "Payment successful!\n";
}
}
int main() {
checkout(StripeProcessor(), 99.99);
checkout(PayPalProcessor(), 49.99);
checkout(CryptoProcessor(), 199.00);
}
public static void checkout(PaymentProcessor processor, double amount) {
if (processor.charge(amount)) {
System.out.println("Payment successful!");
}
}
public static void main(String[] args) {
checkout(new StripeProcessor(), 99.99);
checkout(new PayPalProcessor(), 49.99);
checkout(new CryptoProcessor(), 199.00);
}
static void Checkout(IPaymentProcessor processor, double amount) {
if (processor.Charge(amount)) {
Console.WriteLine("Payment successful!");
}
}
static void Main() {
Checkout(new StripeProcessor(), 99.99);
Checkout(new PayPalProcessor(), 49.99);
Checkout(new CryptoProcessor(), 199.00);
}
Many specific interfaces > one general interface
from abc import ABC, abstractmethod
# BAD — fat interface
class Worker(ABC):
@abstractmethod
def work(self) -> None: pass
@abstractmethod
def eat(self) -> None: pass
@abstractmethod
def sleep(self) -> None: pass
class Robot(Worker):
def work(self) -> None: pass
def eat(self) -> None: raise RuntimeError("Robots don't eat!")
def sleep(self) -> None: raise RuntimeError("Robots don't sleep!")
# GOOD — segregated interfaces
class Workable(ABC):
@abstractmethod
def work(self) -> None: pass
class Eatable(ABC):
@abstractmethod
def eat(self) -> None: pass
class Sleepable(ABC):
@abstractmethod
def sleep(self) -> None: pass
class Human(Workable, Eatable, Sleepable):
def work(self) -> None: pass
def eat(self) -> None: pass
def sleep(self) -> None: pass
// BAD — fat interface
class Worker {
public:
virtual void work() = 0;
virtual void eat() = 0;
virtual void sleep() = 0;
virtual ~Worker() = default;
};
class Robot : public Worker {
public:
void work() override {}
void eat() override { throw std::runtime_error("Robots don't eat!"); }
void sleep() override { throw std::runtime_error("Robots don't sleep!"); }
};
// GOOD — segregated interfaces
class Workable { public: virtual void work() = 0; virtual ~Workable() = default; };
class Eatable { public: virtual void eat() = 0; virtual ~Eatable() = default; };
class Sleepable{ public: virtual void sleep() = 0; virtual ~Sleepable() = default; };
class Human : public Workable, public Eatable, public Sleepable {
public:
void work() override {}
void eat() override {}
void sleep() override {}
};
// BAD — fat interface
interface Worker {
void work();
void eat();
void sleep();
}
class Robot implements Worker {
public void work() {}
public void eat() { throw new RuntimeException("Robots don't eat!"); }
public void sleep() { throw new RuntimeException("Robots don't sleep!"); }
}
// GOOD — segregated interfaces
interface Workable { void work(); }
interface Eatable { void eat(); }
interface Sleepable { void sleep(); }
class Human implements Workable, Eatable, Sleepable {
public void work() {}
public void eat() {}
public void sleep() {}
}
// BAD — fat interface
interface IWorker {
void Work();
void Eat();
void Sleep();
}
class Robot : IWorker {
public void Work() {}
public void Eat() => throw new Exception("Robots don't eat!");
public void Sleep() => throw new Exception("Robots don't sleep!");
}
// GOOD — segregated interfaces
interface IWorkable { void Work(); }
interface IEatable { void Eat(); }
interface ISleepable { void Sleep(); }
class Human : IWorkable, IEatable, ISleepable {
public void Work() {}
public void Eat() {}
public void Sleep() {}
}
from abc import ABC, abstractmethod
from typing import Callable
class Database(ABC):
@abstractmethod
def connect(self) -> None:
pass
@abstractmethod
def execute(self, query: str) -> None:
pass
@abstractmethod
def commit(self) -> None:
pass
@abstractmethod
def rollback(self) -> None:
pass
# Concrete method (template method pattern)
def transaction(self, work: Callable[[], None]) -> None:
self.connect()
try:
work()
self.commit()
except Exception:
self.rollback()
raise
class Database {
public:
virtual ~Database() = default;
virtual void connect() = 0;
virtual void execute(const std::string& query) = 0;
virtual void commit() = 0;
virtual void rollback() = 0;
// Concrete method (template method pattern)
template<typename F>
void transaction(std::function<void()> work) {
connect();
try {
work();
commit();
} catch (...) {
rollback();
throw;
}
}
};
public abstract class Database {
public abstract void connect();
public abstract void execute(String query);
public abstract void commit();
public abstract void rollback();
public void transaction(Runnable work) {
connect();
try {
work.run();
commit();
} catch (Exception e) {
rollback();
throw new RuntimeException(e);
}
}
}
public abstract class Database {
public abstract void Connect();
public abstract void Execute(string query);
public abstract void Commit();
public abstract void Rollback();
public void Transaction(Action work) {
Connect();
try {
work();
Commit();
} catch {
Rollback();
throw;
}
}
}
from abc import ABC, abstractmethod
class HTTPClient(ABC):
@abstractmethod
def request(self, method: str, url: str, data: str = "") -> str:
pass
def get(self, url: str) -> str:
return self.request("GET", url)
def post(self, url: str, data: str = "") -> str:
return self.request("POST", url, data)
def put(self, url: str, data: str = "") -> str:
return self.request("PUT", url, data)
def delete(self, url: str) -> str:
return self.request("DELETE", url)
class HTTPClient {
public:
virtual ~HTTPClient() = default;
virtual std::string request(std::string method, std::string url, std::string data = "") = 0;
std::string get(std::string url) { return request("GET", url, ""); }
std::string post(std::string url, std::string data = "") { return request("POST", url, data); }
std::string put(std::string url, std::string data = "") { return request("PUT", url, data); }
std::string del(std::string url) { return request("DELETE", url, ""); }
};
public abstract class HTTPClient {
public abstract String request(String method, String url, String data);
public String get(String url) { return request("GET", url, ""); }
public String post(String url, String data) { return request("POST", url, data); }
public String put(String url, String data) { return request("PUT", url, data); }
public String delete(String url) { return request("DELETE", url, ""); }
}
public abstract class HttpClient {
public abstract string Request(string method, string url, string data = "");
public string Get(string url) => Request("GET", url);
public string Post(string url, string data) => Request("POST", url, data);
public string Put(string url, string data) => Request("PUT", url, data);
public string Delete(string url) => Request("DELETE", url);
}
from abc import ABC, abstractmethod
from typing import Callable, List
class DataExporter(ABC):
@abstractmethod
def write_header(self) -> None:
pass
@abstractmethod
def write_row(self, data: dict) -> None:
pass
@abstractmethod
def write_footer(self) -> None:
pass
# Concrete template method
def export(self, data: List[dict]) -> None:
self.write_header()
for row in data:
self.write_row(row)
self.write_footer()
class CSVExporter(DataExporter):
def write_header(self) -> None:
print("id,name,email")
def write_row(self, data: dict) -> None:
print(f"{data['id']},{data['name']},{data['email']}")
def write_footer(self) -> None:
print("# End of CSV")
class JSONExporter(DataExporter):
def write_header(self) -> None:
print("[")
def write_row(self, data: dict) -> None:
print(f' {{"id": {data["id"]}, "name": "{data["name"]}", "email": "{data["email"]}"}},')
def write_footer(self) -> None:
print("]")
#include <vector>
#include <string>
#include <iostream>
class DataExporter {
public:
virtual ~DataExporter() = default;
virtual void writeHeader() = 0;
virtual void writeRow(const std::string& data) = 0;
virtual void writeFooter() = 0;
// Concrete template method
void export(const std::vector<std::string>& data) {
writeHeader();
for (const auto& row : data) writeRow(row);
writeFooter();
}
};
class CSVExporter : public DataExporter {
void writeHeader() override { std::cout << "id,name,email\n"; }
void writeRow(const std::string& data) override { std::cout << data << "\n"; }
void writeFooter() override { std::cout << "# End of CSV\n"; }
};
class JSONExporter : public DataExporter {
void writeHeader() override { std::cout << "[\n"; }
void writeRow(const std::string& data) override { std::cout << " " << data << ",\n"; }
void writeFooter() override { std::cout << "]\n"; }
};
public abstract class DataExporter {
public abstract void writeHeader();
public abstract void writeRow(String data);
public abstract void writeFooter();
// Concrete template method
public void export(List<String> data) {
writeHeader();
for (String row : data) writeRow(row);
writeFooter();
}
}
class CSVExporter extends DataExporter {
public void writeHeader() { System.out.println("id,name,email"); }
public void writeRow(String data) { System.out.println(data); }
public void writeFooter() { System.out.println("# End of CSV"); }
}
class JSONExporter extends DataExporter {
public void writeHeader() { System.out.print("[\n"); }
public void writeRow(String data) { System.out.println(" " + data + ","); }
public void writeFooter() { System.out.println("]"); }
}
public abstract class DataExporter {
public abstract void WriteHeader();
public abstract void WriteRow(string data);
public abstract void WriteFooter();
// Concrete template method
public void Export(IEnumerable<string> data) {
WriteHeader();
foreach (var row in data) WriteRow(row);
WriteFooter();
}
}
public sealed class CSVExporter : DataExporter {
public override void WriteHeader() => Console.WriteLine("id,name,email");
public override void WriteRow(string data) => Console.WriteLine(data);
public override void WriteFooter() => Console.WriteLine("# End of CSV");
}
public sealed class JSONExporter : DataExporter {
public override void WriteHeader() => Console.WriteLine("[");
public override void WriteRow(string data) => Console.WriteLine(" " + data + ",");
public override void WriteFooter() => Console.WriteLine("]");
}
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def collide_with(self, other: 'Shape') -> str:
pass
def collide(self, other: 'Shape') -> str:
return other.collide_with(self)
class Circle(Shape):
def collide_with(self, other: 'Shape') -> str:
if isinstance(other, Circle):
return "Circle-Circle"
return "Circle-Other"
class Rectangle(Shape):
def collide_with(self, other: 'Shape') -> str:
if isinstance(other, Rectangle):
return "Rect-Rect"
return "Rect-Other"
# Usage
circle = Circle()
rect = Rectangle()
print(circle.collide(rect)) # Circle-Rect
print(rect.collide(circle)) # Circle-Rect (double dispatch!)
#include <memory>
#include <string>
class Shape {
public:
virtual ~Shape() = default;
virtual std::string collideWith(const Shape& other) const = 0;
std::string collide(const Shape& other) const { return other.collideWith(*this); }
};
class Circle : public Shape {
std::string collideWith(const Shape& other) const override {
if (dynamic_cast<const Circle*>(&other)) return "Circle-Circle";
return "Circle-Other";
}
};
class Rectangle : public Shape {
std::string collideWith(const Shape& other) const override {
if (dynamic_cast<const Rectangle*>(&other)) return "Rect-Rect";
return "Rect-Other";
}
};
// Usage
Circle circle; Rectangle rect;
circle.collide(rect); // Circle-Rect
rect.collide(circle); // Circle-Rect (double dispatch!)
interface Shape {
String collideWith(Shape other);
default String collide(Shape other) { return other.collideWith(this); }
}
class Circle implements Shape {
public String collideWith(Shape other) {
if (other instanceof Circle) return "Circle-Circle";
return "Circle-Other";
}
}
class Rectangle implements Shape {
public String collideWith(Shape other) {
if (other instanceof Rectangle) return "Rect-Rect";
return "Rect-Other";
}
}
// Usage
Shape circle = new Circle();
Shape rect = new Rectangle();
circle.collide(rect); // Circle-Rect
rect.collide(circle); // Circle-Rect (double dispatch!)
public interface IShape {
string CollideWith(IShape other);
string Collide(IShape other) => other.CollideWith(this);
}
public sealed class Circle : IShape {
public string CollideWith(IShape other) => other is Circle ? "Circle-Circle" : "Circle-Other";
}
public sealed class Rectangle : IShape {
public string CollideWith(IShape other) => other is Rectangle ? "Rect-Rect" : "Rect-Other";
}
// Usage
var circle = new Circle();
var rect = new Rectangle();
circle.Collide(rect); // Circle-Rect
rect.Collide(circle); // Circle-Rect (double dispatch!)
from typing import Protocol, TypeVar
T = TypeVar('T')
class Comparable(Protocol):
def __lt__(self, other: T) -> bool: ...
def sort(items: list[T]) -> list[T]:
return sorted(items)
# Any type implementing __lt__ works
print(sort([3, 1, 2]))
print(sort(["c", "a", "b"]))
#include <algorithm>
#include <vector>
#include <string>
template<typename T>
requires std::sortable<T>
std::vector<T> sort(std::vector<T> items) {
std::ranges::sort(items);
return items;
}
// Any type with operator< works
std::vector<int> v1 = {3, 1, 2};
std::vector<std::string> v2 = {"c", "a", "b"};
auto s1 = sort(v1);
auto s2 = sort(v2);
import java.util.*;
public class Sorter {
public static <T extends Comparable<T>> List<T> sort(List<T> items) {
var copy = new ArrayList<>(items);
copy.sort(Comparator.naturalOrder());
return copy;
}
public static void main(String[] args) {
System.out.println(sort(List.of(3, 1, 2)));
System.out.println(sort(List.of("c", "a", "b")));
}
}
using System;
using System.Collections.Generic;
using System.Linq;
public static class Sorter {
public static List<T> Sort<T>(List<T> items) where T : IComparable<T> {
var copy = items.ToList();
copy.Sort();
return copy;
}
static void Main() {
Console.WriteLine(string.Join(", ", Sort(new List<int> { 3, 1, 2 })));
Console.WriteLine(string.Join(", ", Sort(new List<string> { "c", "a", "b" })));
}
}