
Python
Advanced polymorphism includes structural typing with protocols, generic programming with TypeVar, and sophisticated duck typing patterns. These techniques enable flexible, type-safe code without rigid class hierarchies.
Protocols define interfaces without requiring explicit inheritance. Any object with the right methods satisfies a protocol.
from typing import Protocol
class Drawable(Protocol):
"""Protocol for drawable objects"""
def draw(self) -> str:
...
class Circle:
def draw(self) -> str:
return "Drawing circle"
class Square:
def draw(self) -> str:
return "Drawing square"
class Renderer:
def render(self, drawable: Drawable) -> None:
print(drawable.draw())
renderer = Renderer()
renderer.render(Circle()) # Works - Circle satisfies Drawable
renderer.render(Square()) # Works - Square satisfies Drawable
# No explicit inheritance needed!Use TypeVar for type-safe generic programming without losing flexibility.
from typing import TypeVar, Generic, List
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self):
self.items: List[T] = []
def push(self, item: T) -> None:
self.items.append(item)
def pop(self) -> T:
return self.items.pop()
def is_empty(self) -> bool:
return len(self.items) == 0
# Type-safe stack
int_stack: Stack[int] = Stack()
int_stack.push(1)
int_stack.push(2)
print(int_stack.pop()) # Type checker knows this is int
str_stack: Stack[str] = Stack()
str_stack.push("hello")
print(str_stack.pop()) # Type checker knows this is strCreate protocols for complex behaviors.
from typing import Protocol, Iterator
class Container(Protocol):
"""Objects that can be iterated"""
def __iter__(self) -> Iterator:
...
def __len__(self) -> int:
...
class CustomCollection:
def __init__(self, data):
self.data = data
def __iter__(self):
return iter(self.data)
def __len__(self):
return len(self.data)
def process_collection(col: Container) -> None:
print(f"Length: {len(col)}")
for item in col:
print(f"Item: {item}")
collection = CustomCollection([1, 2, 3])
process_collection(collection)Treat functions as first-class polymorphic objects.
from typing import Callable, Union
class Operation:
def __init__(self, func: Callable[[int, int], int], name: str):
self.func = func
self.name = name
def execute(self, a: int, b: int) -> int:
result = self.func(a, b)
print(f"{self.name}: {a} and {b} = {result}")
return result
add = Operation(lambda x, y: x + y, "Add")
multiply = Operation(lambda x, y: x * y, "Multiply")
subtract = Operation(lambda x, y: x - y, "Subtract")
operations = [add, multiply, subtract]
for op in operations:
op.execute(10, 5)from typing import Protocol, List, Dict
class DataSource(Protocol):
def fetch(self) -> List[Dict]:
...
class CSVDataSource:
def fetch(self) -> List[Dict]:
return [{"name": "Alice", "age": 25}]
class APIDataSource:
def fetch(self) -> List[Dict]:
return [{"name": "Bob", "age": 30}]
class DatabaseDataSource:
def fetch(self) -> List[Dict]:
return [{"name": "Charlie", "age": 35}]
class DataPipeline:
def __init__(self, source: DataSource):
self.source = source
def process(self):
data = self.source.fetch()
return [item for item in data if item["age"] >= 25]
# Works with any DataSource
csv_pipeline = DataPipeline(CSVDataSource())
api_pipeline = DataPipeline(APIDataSource())
db_pipeline = DataPipeline(DatabaseDataSource())
print(csv_pipeline.process())
print(api_pipeline.process())from typing import TypeVar, Generic, List, Optional
T = TypeVar('T')
class Repository(Generic[T]):
def __init__(self):
self.items: List[T] = []
def add(self, item: T) -> None:
self.items.append(item)
def get_all(self) -> List[T]:
return self.items.copy()
def find(self, predicate) -> Optional[T]:
for item in self.items:
if predicate(item):
return item
return None
class User:
def __init__(self, id: int, name: str):
self.id = id
self.name = name
class Product:
def __init__(self, id: int, name: str, price: float):
self.id = id
self.name = name
self.price = price
# Type-safe repositories
user_repo: Repository[User] = Repository()
user_repo.add(User(1, "Alice"))
user_repo.add(User(2, "Bob"))
user = user_repo.find(lambda u: u.name == "Alice")
if user:
print(f"Found: {user.name}")
product_repo: Repository[Product] = Repository()
product_repo.add(Product(1, "Laptop", 999.99))
product = product_repo.find(lambda p: p.price > 500)
if product:
print(f"Expensive product: {product.name}")| Concept | Remember |
|---|---|
| Protocol | Structural interface without inheritance |
| TypeVar | Generic type parameter for type safety |
| Generic | Base class for generic types |
| Duck Typing | Object capabilities matter, not type |
| Type Hints | Document and verify types |
| Structural Subtyping | Interfaces based on structure, not names |
| Functional Polymorphism | Functions as polymorphic objects |
| Flexibility | Achieve polymorphism without rigid hierarchies |
Continue with advanced encapsulation patterns.
Ready to practice? Try challenges or explore more concepts
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward