OOP Inheritance සිංහලෙන්: Python වලින් Car, SportsCar උදාහරණයක් - SC Guide

කොහොමද යාලුවනේ! අද අපි කතා කරන්න යන්නේ software development වල ගොඩක්ම වැදගත් concept එකක් ගැන – ඒ තමයි OOP හෙවත් Object-Oriented Programming වල 'Inheritance' කියන එක. මේක හරියට පවුලක දරුවෙක්ට අම්මා තාත්තාගෙන් දේපල ලැබෙනවා වගේ වැඩක්. හරි, එහෙනම් මේක මොකද්ද, මොකටද මේක පාවිච්චි කරන්නේ කියලා අපි සරලවම බලමු.
නැත්නම් මෙහෙම හිතන්නකෝ, අපිට Car
එකක් ගැන class එකක් හදන්න ඕන කියලා. ඒකට make
, model
, year
වගේ attributes (දේපල) වගේම start_engine()
, accelerate()
වගේ methods (වැඩ ටික) ගොඩක් එනවා. හැබැයි දැන් අපිට ඕන SportsCar
එකක් ගැනත් class එකක් හදන්න. SportsCar
එකත් Car
එකක්නේ. එතකොට Car
එකට තියෙන attributes, methods ඔක්කොම SportsCar
එකටත් තියෙනවා.
මෙතනදී අපිට පුළුවන් Car
class එකේ තියෙන දේවල් reuse කරලා, SportsCar
class එක Car
class එකෙන් 'inherit' කරන්න. එතකොට Car
එකේ තියෙන දේවල් ආපහු SportsCar
එකේ ලියන්න ඕන වෙන්නේ නෑ. වැඩේ ලේසි වෙනවා නේද? අද අපි Python වලින් මේක කොහොමද කරන්නේ කියලා, ලංකාවේ විදියට, සරලව කතා කරමු.
Inheritance කියන්නේ මොකද්ද? (is-a relationship)
Inheritance කියන්නේ OOP වල core pillars හතරෙන් එකක්. (අනිත් තුන තමයි Encapsulation, Polymorphism, Abstraction). සරලවම කිව්වොත්, එක class එකක තියෙන attributes (දේපළ) සහ methods (වැඩ ටික) තව class එකකට උරුම කරගන්න පුළුවන්කම.
මේකට කියනවා 'is-a relationship' එකක් කියලා. උදාහරණයක් විදියට:
- A 'SportsCar' is a 'Car'.
- A 'Dog' is an 'Animal'.
- A 'Smartphone' is a 'Device'.
මේ is-a relationship එක හරියට තේරුම් ගන්න එක Inheritance හරියට පාවිච්චි කරන්න අත්යවශ්යයි. අපේ SportsCar
උදාහරණය ගත්තොත්, SportsCar
එක කියන්නේ Car
වර්ගයක්. ඒ කියන්නේ, Car
එකට තියෙන wheels
, engine
, doors
වගේ දේවල් SportsCar
එකටත් තියෙනවා. ඒ වගේම start_engine()
, accelerate()
වගේ actions (methods) SportsCar
එකටත් apply වෙනවා. හැබැයි SportsCar
එකට තමන්ටම ආවේණික features (උදා: turbo_boost()
) වගේ දේවලුත් තියෙන්න පුළුවන්.
මේ විදියට code reuse කරන්න පුළුවන් වෙන එක, code එක maintain කරන්න ලේසි වෙන එක, scalability වැඩි වෙන එක Inheritance වල ප්රධාන වාසි.
Parent සහ Child Classes
Inheritance වලදී class දෙකක් අතර සම්බන්ධයක් හැදෙනවා. මේ class දෙක හඳුන්වන්නේ 'Parent Class' (හෝ Base Class / Super Class) සහ 'Child Class' (හෝ Derived Class / Sub Class) කියලා.
Parent Class:
මේක තමයි වැඩිමහල්ලා. මේ class එකේ තියෙන attributes සහ methods තමයි child class එකට උරුම වෙන්නේ. අපේ උදාහරණයේ Car
class එක තමයි Parent Class එක.
Child Class:
මේක තමයි දරුවා. මේ class එක Parent class එකෙන් attributes සහ methods උරුම කරගන්නවා. ඒ වගේම තමන්ටම ආවේණික attributes සහ methods අලුතෙන් එකතු කරගන්නත් පුළුවන්. නැත්නම් Parent class එකේ තියෙන methods වලට වඩා වෙනස් විදියට වැඩ කරන්නත් පුළුවන් (ඒක තමයි Method Overriding).
Python වලදී Child class එකක් හදද්දී Parent class එක නම parentheses ඇතුලේ දාලා define කරනවා. මෙන්න මෙහෙමයි:
class ParentClass:
# Parent class attributes and methods
class ChildClass(ParentClass):
# Child class attributes and methods
දැන් Car
සහ SportsCar
වලින් බලමු:
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.speed = 0
def start_engine(self):
return f"{self.make} {self.model} engine started."
def accelerate(self, amount):
self.speed += amount
return f"{self.make} {self.model} accelerating. Current speed: {self.speed} km/h."
class SportsCar(Car): # SportsCar is a Child of Car
def __init__(self, make, model, year, top_speed):
super().__init__(make, model, year) # Call Parent's constructor
self.top_speed = top_speed
def activate_turbo(self):
return f"{self.make} {self.model} activating turbo boost! Maximum speed: {self.top_speed} km/h.
"
මෙතන SportsCar
class එක Car
class එකෙන් inherit කරනවා. ඒ කියන්නේ Car
class එකේ තියෙන make
, model
, year
, speed
වගේ attributes වගේම start_engine()
, accelerate()
වගේ methods SportsCar
object එකකටත් පාවිච්චි කරන්න පුළුවන්.
Overriding Methods සහ super() Magic එක
කලින් කිව්වා වගේ, Child class එකකට පුළුවන් Parent class එකේ තියෙන method එකක් තමන්ට ඕන විදියට වෙනස් කරන්න. මේකට කියනවා 'Method Overriding' කියලා.
උදාහරණයක් විදියට, සාමාන්ය Car
එකක් accelerate කරනවට වඩා SportsCar
එකක් accelerate කරන විදිය වෙනස් වෙන්න පුළුවන්. එතකොට අපිට පුළුවන් SportsCar
class එකේ accelerate()
method එක override කරන්න.
Python වලදී Method Overriding කරන්න හරිම ලේසියි. Child class එකේ Parent class එකේ තියෙන method එකම නමින් අලුතෙන් define කරන්න විතරයි තියෙන්නේ. Python interpreter එක child class එකේ method එක detect කරලා, Parent එකේ method එකට වඩා Child එකේ method එක execute කරනවා.
super()
function එක:
දැන් පොඩි ප්රශ්නයක් එනවා. සමහර වෙලාවට අපිට Child class එකේදී Parent class එකේ method එකේ functionality එකත් ඕන වෙනවා, හැබැයි ඒකට අමතරව තව ටිකක් එකතු කරන්නත් ඕන වෙනවා. එතකොට තමයි super()
කියන magic function එක වැඩට එන්නේ.
super()
function එකෙන් අපිට Parent class එකේ methods වලට access කරන්න පුළුවන්. විශේෂයෙන්ම Child class එකේ constructor (__init__
) එක ඇතුලේ Parent class එකේ constructor එක call කරන්න මේක පාවිච්චි කරනවා.
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.speed = 0
print(f"Car {make} {model} created.")
def accelerate(self, amount):
self.speed += amount
print(f"{self.make} {self.model} accelerating. Current speed: {self.speed} km/h.")
class SportsCar(Car):
def __init__(self, make, model, year, top_speed):
super().__init__(make, model, year) # Calling Car's __init__
self.top_speed = top_speed
print(f"SportsCar {make} {model} created with top speed {top_speed}.")
def accelerate(self, amount): # Overriding accelerate method
if self.speed + amount > self.top_speed:
print(f"Cannot accelerate beyond top speed {self.top_speed} km/h.")
self.speed = self.top_speed
else:
# Calling Car's accelerate but with boosted amount
super().accelerate(amount * 2)
print(f"SportsCar {self.make} {self.model} accelerating with extra boost!")
මේ උදාහරණයෙන් පේනවා නේද, SportsCar
එකේ __init__
එක ඇතුලේ අපි super().__init__(make, model, year)
කියලා Parent Class එකේ constructor එක call කරනවා. ඒ වගේම accelerate
method එක override කරලා, ඒක ඇතුලෙත් super().accelerate(amount * 2)
කියලා Parent Class එකේ accelerate
method එක call කරනවා, හැබැයි amount එක දෙගුණයක් කරලා. වැඩේ නියමයි නේද!
ප්රායෝගික උදාහරණයක්: SportsCar එකක් හදමු!
දැන් අපි බලමු මේ concepts ටික එකට එකතු කරලා කොහොමද Car
සහ SportsCar
class හදන්නේ කියලා. මේක ටිකක් දිග code එකක්, හැබැයි කලින් කතා කරපු හැමදේම මේකේ තියෙනවා.
# Parent Class: Car
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.speed = 0
print(f"Car {self.make} {self.model} ({self.year}) created.")
def start_engine(self):
print(f"{self.make} {self.model}'s engine started. Vroom!")
return True
def accelerate(self, amount):
self.speed += amount
print(f"{self.make} {self.model} accelerating. Current speed: {self.speed} km/h.")
return self.speed
def brake(self):
self.speed = 0
print(f"{self.make} {self.model} stopped.")
return self.speed
def get_info(self):
return f"This is a {self.year} {self.make} {self.model}."
# Child Class: SportsCar - Inherits from Car
class SportsCar(Car):
def __init__(self, make, model, year, top_speed, spoiler_type="adjustable"):
super().__init__(make, model, year) # Initialize Parent class attributes
self.top_speed = top_speed
self.spoiler_type = spoiler_type
print(f"SportsCar {self.make} {self.model} ({self.year}) created with top speed {self.top_speed} km/h.")
# Overriding the accelerate method
def accelerate(self, amount):
# We can add sports car specific acceleration logic here
boost_amount = amount * 1.5 # Sports cars accelerate faster!
# Call the parent's accelerate method with the boosted amount
# This reuses the logic from the Car class
current_speed = super().accelerate(boost_amount)
if current_speed >= self.top_speed * 0.8: # Activate turbo if close to max speed
print(f" --> Turbo boost engaging for {self.make} {self.model}!")
return current_speed
# New method specific to SportsCar
def engage_sport_mode(self):
print(f"{self.make} {self.model} engaging sport mode! Spoiler set to {self.spoiler_type}.")
self.speed_limit = self.top_speed
return True
# Overriding get_info method to add SportsCar specific info
def get_info(self):
parent_info = super().get_info() # Get parent's info
return f"{parent_info} It's a SportsCar with a top speed of {self.top_speed} km/h and {self.spoiler_type} spoiler."
# --- Test the classes ---
print("\n--- Creating a normal Car ---")
my_car = Car("Toyota", "Corolla", 2020)
print(my_car.get_info())
my_car.start_engine()
my_car.accelerate(50)
my_car.brake()
print("-" * 30)
print("\n--- Creating a Sports Car ---")
my_sports_car = SportsCar("Ferrari", "488 GTB", 2022, 330, "fixed")
print(my_sports_car.get_info())
my_sports_car.start_engine() # Inherited from Car
my_sports_car.accelerate(80) # Overridden method
my_sports_car.accelerate(120) # Overridden method, approaching top speed
my_sports_car.engage_sport_mode() # SportsCar specific method
my_sports_car.accelerate(100) # Overridden method, going further
my_sports_car.brake() # Inherited from Car
print("-" * 30)
# Demonstrating attribute access
print(f"My sports car make: {my_sports_car.make}") # Inherited attribute
print(f"My sports car top speed: {my_sports_car.top_speed}") # SportsCar specific attribute
මේ code එක run කරලා බලන්න. Car
එකටත්, SportsCar
එකටත් තියෙන methods කොහොමද වැඩ කරන්නේ කියලා. accelerate()
method එකේ වෙනසත්, SportsCar
එකට විතරක් තියෙන engage_sport_mode()
method එකත් පැහැදිලිව පේනවා නේද?
පොඩි අවුල් සහගත තැන්: MRO සහ super().__init__() අමතක වුණොත්
Inheritance කියන්නේ powerful concept එකක් වුණාට, හරියට පාවිච්චි නොකළොත් පොඩි ප්රශ්න ඇතිවෙන්නත් පුළුවන්. විශේෂයෙන්ම, multi-level inheritance (class A -> B -> C) වගේ complicated scenarios වලදී.
MRO (Method Resolution Order):
Python වලදී method එකක් call කරද්දී, interpreter එක class hierarchy එකේ method එක හොයන පිළිවෙලක් තියෙනවා. මේකට තමයි MRO කියන්නේ. සාමාන්යයෙන්, Python DLR (Depth-First Left-to-Right) algorithm එකක් පාවිච්චි කරනවා. ClassName.mro()
method එකෙන් අපිට MRO එක බලන්න පුළුවන්.
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
print(D.mro())
# Output: [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
මේක තවදුරටත් complicate වෙන්න පුළුවන් Multiple Inheritance වලදී (එක class එකක් class කිහිපයකින් inherit කරනවා නම්). හැබැයි අදට අපි මේ ගැන ගැඹුරට කතා කරන්නේ නෑ, දැනට මෙහෙම දෙයක් තියෙනවා කියලා දැනගෙන හිටියොත් ඇති.
super().__init__()
call කරන්න අමතක වුණොත්:
Child class එකක් හදද්දී, __init__
method එක override කරනවා නම්, Parent class එකේ __init__
එකට අදාල attributes initialize කරන්න super().__init__()
call කරන්න අමතක කරන්න එපා. නැත්නම් Parent class එකේ attributes Child object එකට initialize වෙන්නේ නෑ, ඒ වෙලාවට AttributeError
වගේ errors එන්න පුළුවන්.
class Car:
def __init__(self, make, model):
self.make = make
self.model = model
class SportsCar(Car):
def __init__(self, make, model, top_speed):
# super().__init__(make, model) # If this line is commented out...
self.top_speed = top_speed
# my_sports_car = SportsCar("Porsche", "911", 310)
# print(my_sports_car.make) # This will cause an AttributeError!
මේ වගේ පොඩි වැරදි නිසා debug කරන්න ගොඩක් වෙලා යන්න පුළුවන්. ඒ නිසා super().__init__()
call කරන එක අමතක නොකර ඉන්න.
Best Practices: නිකන් Inheritance පාවිච්චි නොකර ඉමු
Inheritance ගොඩක් powerful වුණාට, හැම වෙලාවෙම ඒකම පාවිච්චි කරන්න ඕන නෑ. වැරදි විදියට පාවිච්චි කළොත් code base එක complicate වෙන්න පුළුවන්.
"Is-a" Relationship:
Inheritance පාවිච්චි කරන්න ඕන 'is-a relationship' එකක් තියෙනවා නම් විතරයි. A 'SportsCar' is a 'Car'. A 'Square' is a 'Rectangle'. A 'Dog' is an 'Animal'. මේ වගේ තැන් වලට inheritance නියමයි.
"Has-a" Relationship (Composition):
සමහර වෙලාවට අපිට ඕන වෙන්නේ 'has-a relationship' එකක්. A 'Car' has an 'Engine'. A 'Person' has a 'Heart'. මේ වගේ තැන් වලට Composition (object එකක් ඇතුලේ තව object එකක් instance කරන එක) තමයි හොඳම විසඳුම. Inheritance වලට වඩා Composition preferred වෙන අවස්ථා ගොඩක් තියෙනවා, මොකද ඒකෙන් flexibility එක වැඩි කරනවා.
ඉතින්, inheritance පාවිච්චි කරන්න කලින් දෙපාරක් හිතන්න. ඇත්තටම is-a relationship එකක්ද කියලා. නැත්නම් composition ගැන හිතන එක හොඳයි.
නිගමන
ඔන්න එහෙනම් යාලුවනේ, අද අපි OOP වල Inheritance කියන concept එක ගැන සරලව කතා කළා. Car සහ SportsCar උදාහරණයෙන් මේක කොහොමද Python වලින් implement කරන්නේ කියලත් බැලුවා.
Inheritance කියන්නේ code reuse කරන්න, maintainability වැඩි කරන්න, code base එක organize කරන්න ගොඩක් උදව් වෙන දෙයක්. හැබැයි ඒක හරි තැනට, හරියට පාවිච්චි කරන එක තමයි වැදගත්. super()
function එක ගැනත්, Method Overriding ගැනත් දැන් ඔයාලට හොඳ අවබෝධයක් ඇති කියලා හිතනවා.
මේ article එකෙන් අලුත් දෙයක් ඉගෙන ගත්තා කියලා හිතනවා නම්, comment section එකේ ඔයාලගේ අදහස් කියන්න. මේ code snippets ටික ඔයාලගේ computer එකේ run කරලා බලන්න. එතකොට තවත් හොඳට තේරෙයි.
තවත් මේ වගේ programming concepts ගැන සරලව, සිංහලෙන් කතා කරන article එකකින් හමුවෙමු. එතකන් හැමෝටම සුබ දවසක්!
ජයවේවා!