ইনহেরিটেন্স (Inheritance)

 

কাশেম নামের একজন পুরান ঢাকার লোকের একটি তেহারীর হোটেল ছিল। কাশেমের হোটেলের তেহারীর কদর সারা দেশে রয়েছে। কাশেম মারা যাওয়ার পর পৈতৃক সূত্রে হোটেলের মালিক হয় কাশেম এর ছেলে হাশেম। হাশেম হোটেলের মালিকানা পেয়ে, বিখ্যাত কাশেমের তেহারীর সাথে তার উদ্ভাবিত হাশেমের কাচ্চি ও বিক্রি শুরু করে। হাশেম তার হোটেলে প্রিয় বাবার স্মরণে “আব্বাজান এর স্মরণে শরবত” নামক শরবত ভোক্তাদের বিনামূল্যে তেহারী এবং কাচ্চি এর সাথে পরিবেশন শুরু করে।

 

এইযে এতক্ষন ধরে আমরা একজন বাবা ছেলের গল্প শুনলাম তার উদ্দেশ্য হল ইনহেরিটেন্স শেখা। কাশেমকে আমরা Parent Class ধরি, আর হাশেমকে ধরি Child Class।
– কাশেমের তেহারী তার ছেলে উত্তরাধিকার সূত্রে পেয়েছে, তেমনি প্যারেন্ট ক্লাসের সব বৈশিষ্ট্য (characteristics) পাবে চাইল্ড ক্লাস।
– চাইল্ড ক্লাস চাইলে প্যারেন্ট ক্লাসের বৈশিষ্ট্যকে এক্সটেন্ড করতে পারবে এবং নতুন বৈশিষ্ট্যকে পরিচিত করাতে পারবে। যেমন হাশেম বাবার কাছ থেকে পাওয়া তেহারীর সাথে শরবত দিচ্ছে এবং কাচ্চি পরিচিত করিয়েছে।
– কাশেমের পক্ষে যেমন ছেলে হাশেমের উদ্ভাবিত কাচ্চি আর শরবত পাওয়া সম্ভব নয় তেমনি চাইল্ড ক্লাসের বৈশিষ্ট্য Object oriented programming এর মূল ধারায় প্যারেন্ট ক্লাসে পাবে না।

 

উপরের গল্পটা থেকে ইনহেরিটেন্সের ধারণাটুকু কোডের মাধ্যমে উপস্থাপন করি –
python
class KashemsHotel:
def__init__(self):
    self.hotel_name = "kashem_er_hotel"


deftehari(self):
    print("Tehari, Introduced by Kashem!")


defserve_tehari(self):
    self.tehari()
return "Kashems Tehari"


defserve_kashem(self):
    print(f"Serving {self.serve_tehari()}")


class HashemsHotel(KashemsHotel):
    def__init__(self):
      self.hotel_name = "hashem_er_hotel"


defkacci(self):
    print("Kacci, Introduce by Hashem!")


defserve_kacci(self):
    self.kacci()
return"Kacci"


defabbajan_er_shorone_sorbot(self):
    print("Sorbot, Introduced by Hashem!")


defserve_abbajan_er_shorone_sorbot(self):
    self.abbajan_er_shorone_sorbot()
    return"Abbajan er shorone sorbot"


defserve_hashem(self, food="Tehari"):
    if food == "Tehari":
      print(f"Serving {self.serve_tehari()} and {self.serve_abbajan_er_shorone_sorbot()}")
    else:
      print(f"Serving {self.serve_kacci()} and {self.serve_abbajan_er_shorone_sorbot()}")




print("*** Parent class is called. ***")
kashems_hotel = HashemsHotel()
kashems_hotel.serve_kashem()




print("*** Child class is called. ***")
hashems_hotel = HashemsHotel()
print(">>>Call for parent classes tehari, from child class")
hashems_hotel.serve_hashem("Tehari")
print(">>>Call for child class's Kacci")
hashems_hotel.serve_hashem("Kacci")

 

 
 
আউটপুট
 
// output
*** Parent class is called. ***
Tehari, Introduced by Kashem!
Serving Kashems Tehari
*** Child class is called. ***
>Call for parent classes tehari, from child class
Tehari, Introduced by Kashem!
Sorbot, Introduced by Hashem!
Serving Kashems Tehari and Abbajan er shorone sorbot
>Call for child class's Kacci
Kacci, Introduce by Hashem!
Sorbot, Introduced by Hashem!
Serving Kacci and Abbajan er shorone sorbot

 

 
আমরা এইখানে KashemsHotel ক্লাসকে প্যারেন্ট ক্লাস হিসেবে নিয়েছি আর HashemsHotel ক্লাসকে নিয়েছি চাইল্ড ক্লাস হিসেবে। চাইল্ড ক্লাসে প্যারেন্ট ক্লাসকে ইনহেরিট করতে চাইল্ড ক্লাসের নামের পর প্রথম বন্ধনীর () মধ্যে প্যারেন্ট ক্লাসের নাম লিখতে হয়। একাধিক প্যারেন্ট ক্লাস হলে, কমা দিয়ে দিয়ে লিখতে হয়, যেমনঃ
 
class ChildClass(ParentClass1, ParentClass2, ParentClass3):
    pass

 

 
চাইল্ড ক্লাসে প্যারেন্ট ক্লাসের সকল গুণাগুণ অক্ষুণ্ণ থাকে। চাইল্ড ক্লাসের ইন্সট্যান্স বা অবজেক্ট থেকে প্যারেন্ট ক্লাসের সকল মেথড অ্যাক্সেস করা যায়। যেমনটি আমরা করেছি HashemsHotel চাইল্ড ক্লাস টিতে। আমরা চাইল্ড ক্লাস থেকে KashemsHotel ক্লাসের মেথডকে অ্যাক্সেস করেছি।

 

আমাদের নিশ্চই মনে হচ্ছে, এই ইনহেরিটেন্স এর মাধ্যমে কোড লিখে লাভ কি। লাভতো অবশ্যই আছে। আমাদের সফটওয়্যার ডিজাইনের সময় অনেক কমপ্লেক্স এবং বিশাল কোড লিখতে হয়। আমরা ইনহেরিটেন্স এর মাধ্যমে কমন ফিচারগুলো নিয়ে একটি ক্লাস লিখতে পারি এবং বাকি ফিচারগুলো যার যার ক্লাসে লিখতে পারি, এতে আমাদের কোড এর পরিমান অনেক কমে যায় এবং জটিল হয়ে যায় না, সহজে ম্যানেজ করা যায়। চলো একটা উদাহরণ দেখি-

 

python




class Parent:
    defcommon_feature_1(self):
    print("Common feature 1")


defcommon_feature_2(self):
    print("Common feature 2")


class Child1(Parent):
    defchild_1_feature(self):
    print("Child 1 feature")


class Child2(Parent):
    defchild_2_feature(self):
    print("Child 2 feature")


print("\n** Child 1 Calling **")
child1 = Child1()
child1.common_feature_1()
child1.common_feature_2()
child1.child_1_feature()
print("\n** Child 1 Calling **")
child2 = Child2()
child2.common_feature_1()
child2.common_feature_2()
child2.child_2_feature()




// output
// ** Child 1 Calling **
// Common feature 1
// Common feature 2
// Child 1 feature




// ** Child 1 Calling **
// Common feature 1
// Common feature 2
// Child 2 feature

 

 
এছাড়া আমরা অনেক সময় পাইথনের অনেক বিল্ট-ইন ক্লাসকে ইনহেরিট করি। ঐসব বিল্ট-ইন ক্লাসে শত শত লাইনের কোড লিখা আছে, আমরা শুধু ইনহেরিট করে কাজ করতে পারি আমাদের ইউজার ডিফাইন্ড ক্লাসে। যেমন আমরা পাইথনে অ্যাবস্ট্রাক্ট ক্লাস লিখতে ABC ক্লাস কে ইনহেরিট করি-
 
python
from abc import ABC, abstractmethod




Class AbstractClass(ABC):
    @abstractmethod
defprocess(self):
'''No body'''
 pass

 

 
মেথড ওভাররাইডিং
মেথড ওভাররাইডিংয়ের ব্যাপারটি হলো, আমরা প্যারেন্ট এবং চাইল্ড ক্লাসে একই নামের মেথড লিখতে পারি। চাইল্ড ক্লাসের মেথডটি প্যারেন্ট ক্লাসের মেথডকে ওভাররাইড করে অর্থাৎ প্যারেন্ট ক্লাসের একই নামের মেথডের কার্যকলাপকে আটকিয়ে দিয়ে চাইল্ড ক্লাসের মেথডটি তার কার্যকলাপ প্রদর্শন করে। এক্ষেত্রে, আমরা প্যারেন্ট এবং চাইল্ড ক্লাসের মেথড দুইটিতে প্যারামিটারস এর তারতম্য ঘটাতে পারি, তাদের ক্রিয়াকৌশল পরিবর্তন করে দিতে পারি। উপরের বাবা ছেলের উদাহরণ টিতে আমরা KashemsHotel এবং HashemsHotel ক্লাস দু’টিতে আমরা “address” নামের দু’টি মেথড লিখে দেখি কিভাবে ওভাররাইডিং কাজ করছে-
 
python
class KashemsHotel:
    def__init__(self):
    self.hotel_name = "kashem_er_hotel"


defaddress(self):
    print("123, Puran Dhaka!")


deftehari(self):
    print("Tehari, Introduced by Kashem!")


defserve_tehari(self):
    self.tehari()
    return"Kashems Tehari"


defserve_kashem(self):
    print(f"Serving {self.serve_tehari()}")


class HashemsHotel(KashemsHotel):
    def__init__(self):
    self.hotel_name = "hashem_er_hotel"


defaddress(self):
    print("456, Puran Dhaka!")


defkacci(self):
    print("Kacci, Introduce by Hashem!")


defserve_kacci(self):
    self.kacci()
return"Kacci"


defabbajan_er_shorone_sorbot(self):
    print("Sorbot, Introduced by Hashem!")


defserve_abbajan_er_shorone_sorbot(self):
    self.abbajan_er_shorone_sorbot()
return"Abbajan er shorone sorbot"


defserve_hashem(self, food="Tehari"):
    if food == "Tehari":
      print(f"Serving {self.serve_tehari()} and {self.serve_abbajan_er_shorone_sorbot()}")
    else:
      print(f"Serving {self.serve_kacci()} and {self.serve_abbajan_er_shorone_sorbot()}")




print("*** Parent class is called. ***")
kashems_hotel = HashemsHotel()




print("*** Child class is called. ***")
hashems_hotel = HashemsHotel()
hashems_hotel.address()






আউটপুট


// *** Parent class is called. ***
// *** Child class is called. ***
// 456, Puran Dhaka!

 

 
আমরা আউটপুটে দেখতে পাচ্ছি প্যারেন্ট ক্লাসের “address” মেথডের রেজাল্ট “123, Puran Dhaka!” কে চাইল্ড ক্লাসের “address” মেথডকে ওভাররাইড করেছে এবং রেজাল্ট হিসেবে “456, Puran Dhaka!” প্রিন্ট করেছে।
উল্লেখ্য, আমরা কিন্তু __init__() মেথড কেউ ওভাররাইড করতে পারি, উপরের উদাহরনে আমরা হোটেলের নাম পরিবর্তন করে দিয়েছি এইভাবে।
 
python
print("*** Parent class is called. ***")
kashems_hotel = HashemsHotel()




print("*** Child class is called. ***")
hashems_hotel = HashemsHotel()
print(hashems_hotel.hotel_name)

 

আউটপুট
// *** Parent class is called. ***
// *** Child class is called. ***
// hashem_er_hotel

 

 

 

উদাহরন
class Vehicle:
    def __init__(self,manufacturer):
        self.manufacturer = manufacturer

class Car(Vehicle):
    def __init__(self,manufacturer,model):
        super().__init__(manufacturer)
        self.model = model

class Truck(Vehicle):
    def __init__(self, manufacturer,model):
        super().__init__(manufacturer)
        self.model = model

class Electric(Car):
    def __init__(self, manufacturer, model, charge_time):
        super().__init__(manufacturer, model)
        self.charge_time = charge_time
    
    def __str__(self):
        return f"{self.manufacturer} made {self.model}"


class Petrol(Car):
    def __init__(self, manufacturer, model, capacity):
        super().__init__(manufacturer, model)
        self.capacity = capacity
    
    def __str__(self):
        return f"{self.manufacturer} made {self.model}"


obj1 = Electric("Tesla","Model S" , "5 hour")
obj2 = Petrol("Toyota", "Corolla", "50 Liter")

print(obj1)
print(obj2)

 

 

এসো নিজে করি

১। ইনহেরিটেন্সের ধারনা ব্যবহার করে, Shape, Triangle এবং Square নামের তিনটি ক্লাস তৈরী করুন, যাতে Shape ক্লাসটি হবে Triangle এবং Square class এর প্যারেন্ট ক্লাস। Shape ক্লাসে একটি ফাংশন লিখুন, যা Shape এর নাম রিটার্ন করবে, যা চাইল্ড ক্লাস দু’টি ইনহেরিট করবে। আর দু’টি চাইল্ড ক্লাসে ক্ষেত্রফল ও আয়তন দেখানোর দু’টি ফাংশন লিখুন-

২। নিচের চিত্রটি লক্ষ্য করুন এবং পাইথন দিয়ে এই ৪টি ক্লাস (তাদের নিজস্ব মেথড সহ) তৈরী করুন যেখানে প্রতি ক্লাসের দুইটি করে অবজেক্ট থাকবে।

 
                                                                                                                                                                 inheritance Inheritance
 
 
ইন্টারভিউ প্রশ্নোত্তর
গুরুত্বপূর্ন প্রশ্নসমুহ
– Base Class ও Derived Class বলতে কী বুঝায়?
– পাইথনে Inheritance এর প্রয়োজনীয়তা কী?
– পাইথনের একটি ক্লাস কি একের অধিক ক্লাসকে inherit করতে পারে?
– Method overriding বলতে কী বুঝায়?
– Method overloading বলতে কী বুঝায়?