Polymorphism and Abstract Classes
Polymorphism and Abstract Classes
Section titled “Polymorphism and Abstract Classes”Introduction
Section titled “Introduction”Polymorphism means “many forms” — the ability to use a unified interface to work with objects of different types.
Duck Typing
Section titled “Duck Typing”# "If it walks like a duck and quacks like a duck, it's a duck"
def make_sound(animal): return animal.speak() # Just call the method — no type checking!
class Dog: def speak(self): return "Woof!"
class Cat: def speak(self): return "Meow!"
class Car: def speak(self): return "Vroom!"
for obj in [Dog(), Cat(), Car()]: print(make_sound(obj)) # Works for all!Abstract Base Classes (ABC)
Section titled “Abstract Base Classes (ABC)”from abc import ABC, abstractmethod
class Shape(ABC): @abstractmethod def area(self) -> float: """Calculate area — must be implemented by subclasses.""" pass
@abstractmethod def perimeter(self) -> float: pass
def describe(self): return f"Area: {self.area():.2f}, Perimeter: {self.perimeter():.2f}"
class Circle(Shape): def __init__(self, radius): self.radius = radius
def area(self): return 3.14159 * self.radius ** 2
def perimeter(self): return 2 * 3.14159 * self.radius
# shape = Shape() # TypeError: Can't instantiate abstract classcircle = Circle(5)print(circle.describe()) # Area: 78.54, Perimeter: 31.42Protocol Classes (Structural Subtyping)
Section titled “Protocol Classes (Structural Subtyping)”from typing import Protocol
class Drawable(Protocol): def draw(self) -> str: ...
class Circle: def draw(self): return "Drawing a circle"
class Square: def draw(self): return "Drawing a square"
def render(shape: Drawable): print(shape.draw())
render(Circle()) # OK — Circle implements draw()render(Square()) # OK — Square implements draw()Best Practices
Section titled “Best Practices”- Prefer duck typing for flexibility — it’s the Pythonic way
- Use ABCs when you need to define a formal interface
- Use Protocols when you need type hints without inheritance
- Don’t over-abstract — simple functions are often better than complex hierarchies
Practice Exercises
Section titled “Practice Exercises”Exercise 1: Create a PaymentProcessor ABC with process_payment(amount) and implement CreditCardProcessor and PayPalProcessor.
Exercise 2: Write a function that processes a list of objects that implement a save() method (duck typing).