Inheritance, Polymorphism & Dunder Methods
Inheritance, Polymorphism ও ম্যাজিক মেথড
1. Why Inheritance?
Inheritance lets a new class reuse and extend an existing class. The new class (child / subclass) automatically gets everything the old one (parent / superclass) has, and can add new attributes or override existing methods. Polymorphism is the natural consequence: code that expects a parent type also works transparently with any subclass.
2. Single Inheritance and super()
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "some sound"
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # call parent's __init__
self.breed = breed
def speak(self):
return f"{self.name} ({self.breed}) says woof!"
d = Dog("Tommy", "Labrador")
print(d.speak())
print(isinstance(d, Animal)) # True
super().__init__(name) parent class-এর __init__ call করে। override করা speak method child-এর নিজস্ব।
3. Multiple Inheritance and MRO
Python allows multiple inheritance. When a method is called, Python walks the
Method Resolution Order (MRO) — a linearisation of all ancestor classes —
to decide which version to run. You can inspect it with ClassName.__mro__.
Class.__mro__-এ এই তালিকা দেখা যায়।
class A:
def who(self): return "A"
class B(A):
def who(self): return "B"
class C(A):
def who(self): return "C"
class D(B, C): pass
print(D().who()) # "B"
print([c.__name__ for c in D.__mro__])
4. Dunder (Magic) Methods
Methods with double underscores around the name hook into Python's built-in operations:
len(x) calls x.__len__(), x + y calls x.__add__(y),
print(x) uses x.__str__(), and so on.
len(x) → x.__len__(), x + y → x.__add__(y) ইত্যাদি।
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __str__(self):
return f"Vector({self.x}, {self.y})"
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def __len__(self):
return int((self.x**2 + self.y**2) ** 0.5)
a = Vector(3, 4)
b = Vector(1, 2)
print(a + b) # Vector(4, 6)
print(len(a)) # 5
print(a == Vector(3, 4))
5. Abstract Base Classes (abc)
Sometimes you want to guarantee every subclass implements a certain method. The
abc module lets you mark classes as abstract.
abc module দিয়ে এটি করা যায়।
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self): ...
class Square(Shape):
def __init__(self, side): self.side = side
def area(self): return self.side ** 2
class Circle(Shape):
def __init__(self, r): self.r = r
def area(self): return 3.14159 * self.r ** 2
for s in [Square(4), Circle(3)]:
print(type(s).__name__, "area =", round(s.area(), 2))
6. Composition vs Inheritance
✅ Composition (কম্পোজিশন)
- Object holds other objects as attributes
- Has-a relationship
- Loose coupling, easy to change
- Recommended default in Python
⚠️ Inheritance (ইনহেরিটেন্স)
- Subclass IS-A parent
- Tight coupling — parent changes affect children
- Deep hierarchies become painful
- Use sparingly — 2-3 levels max
7. Vocabulary
| Term | Meaning | বাংলায় |
|---|---|---|
| Subclass | Class that inherits from another. | অন্য class থেকে inherit করা class। |
super() | Proxy to the parent class. | Parent class-এর proxy। |
| MRO | Method Resolution Order. | Method-এর resolution ক্রম। |
| Dunder | Double-underscore method hooked into built-ins. | Built-in operation-এ যুক্ত double-underscore method। |
| ABC | Abstract Base Class — unimplementable blueprint. | Abstract Base Class — implement বাধ্যতামূলক করা blueprint। |
| Polymorphism | Same call, different behaviour by type. | একই call, type অনুযায়ী ভিন্ন আচরণ। |
8. Practice Problems
-
Create
Vehicleand subclassCar(Vehicle)that addswheels=4.Vehicleএবং তার subclassCarলিখুন যেখানেwheels=4।✨ Show Answer
ans1.pyclass Vehicle: def __init__(self, brand): self.brand = brand class Car(Vehicle): def __init__(self, brand): super().__init__(brand) self.wheels = 4 c = Car("Toyota") print(c.brand, c.wheels) -
Write
Moneyclass supporting+between twoMoneyvalues in the same currency.Moneyclass লিখুন যেখানে একই currency-র দুইটি Money যোগ করা যাবে।✨ Show Answer
ans2.pyclass Money: def __init__(self, amount, currency): self.amount, self.currency = amount, currency def __add__(self, other): if self.currency != other.currency: raise ValueError("currency mismatch") return Money(self.amount + other.amount, self.currency) def __str__(self): return f"{self.amount} {self.currency}" print(Money(100, "BDT") + Money(50, "BDT")) -
Explain what
super().__init__()does in one line.এক লাইনে ব্যাখ্যা করুনsuper().__init__()কী করে।✨ Show Answer
Answer: It calls the parent class's
__init__so the parent can do its own initialisation before the child adds or changes anything.এটি parent class-এর
__init__কল করে, যাতে parent-এর নিজস্ব initialisation সম্পন্ন হয়। -
Make a
Playlistclass that supportslen()and iteration using__len__and__iter__.Playlistclass লিখুন যাlen()ও iteration সাপোর্ট করবে।✨ Show Answer
ans4.pyclass Playlist: def __init__(self, songs): self.songs = list(songs) def __len__(self): return len(self.songs) def __iter__(self): return iter(self.songs) p = Playlist(["Runa", "James", "LRB"]) print(len(p)) for s in p: print(s) -
When should you prefer composition over inheritance? Give one concrete example.Composition কখন inheritance-এর চেয়ে ভালো? একটি বাস্তব উদাহরণ দিন।
✨ Show Answer
Answer: When the relation is "has-a" rather than "is-a". Example: a
Carhas anEngine, aGPS, and fourWheels — it does not inherit from them. Composition keeps those components replaceable; inheritance would lock the design into a rigid taxonomy.যখন সম্পর্কটি "has-a", "is-a" নয়। উদাহরণ: একটি
Car-এর একটিEngineও GPS থাকে — তাদের থেকে inherit করে না। Composition-এ component গুলো আলাদাভাবে পরিবর্তন করা যায়।
Summary — Module 23
Subclassing reuses and extends an existing class; super() delegates to the parent.
Python supports multiple inheritance via a well-defined MRO. Dunder methods plug your classes
directly into Python's syntax. Use abc to enforce method contracts, and prefer
composition over deep inheritance hierarchies for maintainable code.
super() parent-এ delegate করে। Python MRO অনুযায়ী multiple inheritance সামলায়। Dunder method class-কে Python-এর built-in syntax-এ যুক্ত করে। গভীর inheritance-এর বদলে composition-কে অগ্রাধিকার দিন।