အခန်း 17 · animation 3 ခု

Chapter 16: OOP – Inheritance (အမွေဆက်ခံခြင်း)

808 Coder မှ တင်ဆက်သည်

အရင်အခန်းမှာ class နဲ့ object ဆောက်တတ်ပြီးပြီ။ အခု OOP ရဲ့ အစွမ်းထက်ဆုံး အယူအဆတွေထဲက တစ်ခုကို လေ့လာမယ် — Inheritance (အမွေဆက်ခံခြင်း)။

လက်တွေ့ဘဝမှာ အမွေဆက်ခံခြင်းဆိုတာ ရင်းနှီးပြီးသား — သားသမီးက မိဘဆီက အမွေရတယ်။ OOP မှာလည်း အတူတူပဲ။ Child class (subclass) တစ်ခုက Parent class (superclass) ဆီက attribute တွေ၊ method တွေကို အလိုအလျောက် ရသွားတယ်။ Code တွေ ထပ်ခါထပ်ခါ ပြန်ရေးစရာ မလိုတော့ဘူး — ဒါကို code reuse လို့ ခေါ်တယ်။ နောက်ထပ် အကျိုးတစ်ခုက hierarchy — class တွေကို အဆင့်ဆင့် စီစဉ်ထားတော့ စနစ်တစ်ခုလုံးရဲ့ ဖွဲ့စည်းပုံကို တစ်ချက်ကြည့်ရုံနဲ့ နားလည်နိုင်တယ်။

ဒီအခန်းပြီးရင်...

  • Inheritance ဆိုတာ ဘာလဲ၊ ဘာကြောင့် သုံးရတာလဲ ရှင်းပြနိုင်မယ်
  • Inheritance ၄ မျိုး (single, multilevel, hierarchical, multiple) ကို ခွဲခြားရေးနိုင်မယ်
  • super().__init__() နဲ့ parent ရဲ့ constructor ကို ခေါ်သုံးနိုင်မယ်
  • MRO (Method Resolution Order) ဆိုတာ ဘာလဲ နားလည်မယ်
  • Inheritance သုံးထားတဲ့ Employee Management System လို program ငယ်တစ်ခု ရေးနိုင်မယ်

Inheritance ဆိုတာဘာလဲ

Inheritance ဆိုတာ class တစ်ခုက နောက်တစ်ခု class ရဲ့ data member (attribute) နဲ့ method တွေကို အမွေဆက်ခံနိုင်တဲ့ စွမ်းရည်ပါ။ အမွေပေးတဲ့ class ကို parent class (သို့ superclass)၊ အမွေရတဲ့ class ကို child class (သို့ subclass) လို့ ခေါ်တယ်။

ဥပမာ — Vehicle ဆိုတဲ့ parent class ရှိတယ်။ Bus, Car, Truck ဆိုတဲ့ child class တွေက Vehicle ကို အမွေဆက်ခံတယ်။ ယာဉ်တိုင်းမှာ လိုတဲ့ အချက် (ဥပမာ — start_engine(), fuel attribute) တွေကို Vehicle မှာ တစ်ခါတည်း ရေးထားလိုက်တယ်။ Bus, Car, Truck တွေက အဲဒါတွေ အလိုအလျောက် ရပြီးသား — ကိုယ်ပိုင်ထူးခြားချက် (ဥပမာ — Bus ရဲ့ open_door()) ကိုပဲ ထပ်ဖြည့်ရေးရုံပဲ။

Syntax က ဒီလိုပါ —

class Parent:
    pass

class Child(Parent):
    pass

Parent class နာမည်ကို လက်သည်းကွင်း ( ) အထဲမှာ ထည့်ရေးလိုက်တာနဲ့ inheritance ဖြစ်သွားပြီ။

Vehicle hierarchy Vehicle parent class (superclass) Bus Car Truck child classes (subclasses) inherit from Vehicle
Vehicle → Bus, Car, Truck inheritance

Reference

Inheritance မသုံးရင် ဘာဖြစ်မလဲ

Inheritance မရှိရင် Bus, Car, Truck သုံးခုလုံးမှာ start_engine(), stop() စတဲ့ method တွေ တစ်ပုံစံတည်း ထပ်ခါထပ်ခါ ရေးရမယ်။ တစ်နေ့ start_engine() မှာ အမှားပြင်ချင်ရင် ၃ နေရာ လိုက်ပြင်ရမယ် — တစ်နေရာမေ့သွားရင် bug ကျန်ခဲ့မယ်။ Inheritance သုံးရင်တော့ parent မှာ တစ်ခါတည်း ပြင်လိုက်ရုံပဲ၊ child အားလုံး အလိုအလျောက် ရသွားတယ်။ ဒါကို code reuse လို့ ခေါ်ပြီး inheritance ရဲ့ အဓိကအကျိုးပဲ။

isinstance() နဲ့ issubclass()

Object တစ်ခုက ဘယ် class အမျိုးအစားလဲ စစ်ဖို့ built-in function ၂ ခု ရှိတယ် —

class Animal:
    pass

class Cat(Animal):
    pass

c = Cat()
print(isinstance(c, Cat))       # True
print(isinstance(c, Animal))    # True — child object ဟာ parent အမျိုးအစားလည်းဖြစ်
print(isinstance(c, str))       # False
print(issubclass(Cat, Animal))  # True
True
True
False
True

Cat object ဟာ Animal လည်း ဖြစ်တယ် — ဒီသဘောက Chapter 17 (polymorphism) မှာ အရေးပါလာမယ်။

Single Inheritance

အရိုးရှင်းဆုံး ပုံစံ — child class တစ်ခုက parent class တစ်ခုတည်းဆီက အမွေဆက်ခံတာ။

class Animal:
    def speak(self):
        print("The animal makes a sound.")

class Cat(Animal):
    def meow(self):
        print("Meow meow!")

c = Cat()
c.speak()   # parent ကနေ အမွေရထားတာ
c.meow()    # ကိုယ်ပိုင် method
The animal makes a sound.
Meow meow!

Cat class မှာ speak() ကို ထပ်ရေးထားတာ မရှိဘူး — ဒါပေမယ့် Animal ကနေ အမွေရထားလို့ သုံးလို့ရတယ်။

မှတ်ချက်

Child class က parent ရဲ့ method ကို ကိုယ့်ဘာသာ ပြန်ရေးပြီး အစားထိုးလို့လည်း ရတယ်။ အဲဒါကို method overriding လို့ ခေါ်ပြီး Chapter 17 မှာ အသေးစိတ် သင်မယ်။

Reference

Multilevel Inheritance

Class A → Class B → Class C — ဆင့်ကဲဆင့်ကဲ အမွေဆက်ခံသွားတာ။ အဘိုး → အဖေ → သား ဆက်ခံသလို။

class Animal:
    def breathe(self):
        print("Breathing...")

class Bird(Animal):
    def fly(self):
        print("Flying in the sky...")

class Eagle(Bird):
    def hunt(self):
        print("Hunting for food...")

e = Eagle()
e.breathe()  # Animal ကနေ (အဘိုး)
e.fly()      # Bird ကနေ (အဖေ)
e.hunt()     # ကိုယ်ပိုင်
Breathing...
Flying in the sky...
Hunting for food...

Eagle object တစ်ခုက method ၃ ခုလုံး သုံးနိုင်တယ် — breathe() က Animal ဆီက တစ်ဆင့်ခံ အမွေရထားတာ။

Reference

Hierarchical Inheritance

Parent တစ်ခုတည်းကနေ child အများအပြား ခွဲထွက်သွားတာ — အဖေတစ်ယောက်တည်းက သားသမီး အများအပြား မွေးသလို။

class Animal:
    def eat(self):
        print("Eating food...")

class Fish(Animal):
    def swim(self):
        print("Swimming in the river...")

class Sparrow(Animal):
    def fly(self):
        print("Flying over the trees...")

f = Fish()
f.eat()
f.swim()

print()

s = Sparrow()
s.eat()
s.fly()
Eating food...
Swimming in the river...

Eating food...
Flying over the trees...

Fish နဲ့ Sparrow နှစ်ခုလုံး Animal က eat() ကို အမွေရတယ်။ ဒါပေမယ့် Fish က fly() မရဘူး၊ Sparrow က swim() မရဘူး — မောင်နှမချင်းအမွေကို မျှဝေတာ မဟုတ်ဘဲ၊ မိဘဆီကပဲ ကိုယ်စီ ရတာ။

Animal hierarchy Animal one parent class Fish Sparrow hierarchical inheritance: one parent, many children
Animal → Fish, Sparrow hierarchical inheritance

Reference

Multiple Inheritance နဲ့ MRO

Child class တစ်ခုက parent class တစ်ခုထက် ပိုပြီး အမွေဆက်ခံတာ။

class Father:
    def talent(self):
        print("Good at carpentry")

class Mother:
    def talent(self):
        print("Good at weaving")

class Child(Father, Mother):
    pass

c = Child()
c.talent()
print(Child.__mro__)
Good at carpentry
(<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>)

Father နဲ့ Mother နှစ်ခုလုံးမှာ talent() ဆိုတဲ့ နာမည်တူ method ရှိတယ်။ ဒီလိုအခါမှာ Python က ဘယ်ဟာကို ရွေးမလဲ? အဖြေက MRO (Method Resolution Order) — Python က parent တွေကို ဘယ်ကနေ ညာကို အစဉ်လိုက် ရှာတယ်။ class Child(Father, Mother) လို့ ရေးထားတော့ ဘယ်ဘက်အကျဆုံး parent (Father) ရဲ့ method က အနိုင်ရတယ်။

__mro__ က Python ရှာမယ့် အစဉ်ကို ပြပေးတယ် — Child → Father → Mother → object။

MRO ကို Child.__mro__ (သို့) Child.mro() နဲ့ အမြဲ စစ်နိုင်တယ်။ Inheritance နက်လာတဲ့အခါ၊ အထူးသဖြင့် multiple inheritance သုံးတဲ့အခါ ဒါကို စစ်ကြည့်တာ အကျင့်ကောင်းပဲ — ဘယ် parent ရဲ့ method အလုပ်လုပ်မလဲ ကြိုသိရတယ်။ MRO ဟာ super() ခေါ်တဲ့အခါမှာလည်း အသုံးဝင်တယ် — super() က MRO အစဉ်အတိုင်း နောက် class ကို ရှာပေးတာမို့ပါ။

သတိပြုရန်

Multiple inheritance သုံးတဲ့အခါ နာမည်တူ method တွေ ရှိနေရင် ဘယ်ဟာ အလုပ်လုပ်မလဲ ဆိုတာ MRO နဲ့ ဆုံးဖြတ်တယ်။ ကိုယ်လိုချင်တဲ့ parent ကို ဘယ်ဘက်အကျဆုံး ထားရေးဖို့ သတိရပါ။

Reference

super().__init__() — Parent ရဲ့ Constructor ကို ခေါ်ခြင်း

Child class မှာ ကိုယ်ပိုင် __init__ ရေးလိုက်ရင်၊ parent ရဲ့ __init__ က အလိုအလျောက် ခေါ်မခံရတော့ဘူး။ ဒါကြောင့် parent ဆီက attribute တွေ လိုချင်ရင် super().__init__() နဲ့ ကိုယ်တိုင် ခေါ်ပေးရတယ်။

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def display_info(self):
        print(f"Name: {self.name}, Age: {self.age}")

class Employee(Person):
    def __init__(self, name, age, emp_id, salary):
        super().__init__(name, age)  # parent ရဲ့ __init__ ကို ခေါ်တာ
        self.emp_id = emp_id
        self.salary = salary

    def display_employee(self):
        self.display_info()
        print(f"Employee ID: {self.emp_id}, Salary: ${self.salary}")

e = Employee("Ma Nyein", 28, "E2001", 4500)
e.display_employee()
Name: Ma Nyein, Age: 28
Employee ID: E2001, Salary: $4500

super() ဆိုတာ "parent class" ကို ဆိုလိုတာ။ super().__init__(name, age) က Person ရဲ့ __init__ ကို ခေါ်ပြီး name, age ကို ပြင်ဆင်ပေးတယ်။ ပြီးမှ Employee က ကိုယ်ပိုင် emp_id, salary ကို ဆက်ဖြည့်တယ်။ အလုပ်ခွဲဝေတာ သန့်ရှင်းတယ်။

သတိပြုရန်

Child ရဲ့ __init__ ထဲမှာ super().__init__() ထည့်ဖို့ မေ့သွားရင် parent က သတ်မှတ်ပေးတဲ့ attribute တွေ (self.name, self.age) ရှိလာမှာ မဟုတ်ဘူး။ နောက်မှ display_info() လို parent method ခေါ်ရင် AttributeError တက်မယ်။

မေ့သွားရင် တကယ်ဘာဖြစ်လဲ ကြည့်ရအောင် —

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def display_info(self):
        print(f"Name: {self.name}, Age: {self.age}")

class BrokenEmployee(Person):
    def __init__(self, name, age, emp_id):
        # super().__init__(name, age) — ဒီစာကြောင်း မေ့သွားတယ်!
        self.emp_id = emp_id

b = BrokenEmployee("Ko Min", 30, "E9999")
print(b.emp_id)
try:
    b.display_info()
except AttributeError as e:
    print("Error:", e)
E9999
Error: 'BrokenEmployee' object has no attribute 'name'

display_info() က self.name ကို ရှာတယ် — ဒါပေမယ့် Person.__init__ ခေါ်မခံရလို့ name ဆိုတာ ဖန်တီးခံရခြင်း မရှိဘူး။ ဒါကြောင့် child ရဲ့ __init__ ရေးတိုင်း super().__init__() ကို ပထမဆုံး စာကြောင်းအဖြစ် ထည့်ဖို့ အကျင့်လုပ်ထားပါ။

super() ကို သာမန် method တွေမှာလည်း သုံးနိုင်တယ်

super() က __init__ အတွက်သီးသန့် မဟုတ်ဘူး — ဘယ် method မှာမဆို parent ရဲ့ version ကို ခေါ်ချင်ရင် သုံးနိုင်တယ် —

class Person:
    def __init__(self, name):
        self.name = name

    def introduce(self):
        print(f"Hi, I am {self.name}.")

class Employee(Person):
    def __init__(self, name, emp_id):
        super().__init__(name)
        self.emp_id = emp_id

    def introduce(self):
        super().introduce()                  # parent ရဲ့ introduce()
        print(f"My employee ID is {self.emp_id}.")

e = Employee("Ma Nyein", "E2001")
e.introduce()
Hi, I am Ma Nyein.
My employee ID is E2001.

Child က parent ရဲ့ အပြုအမူကို အခြေခံပြီး ကိုယ့်အပိုင်း ထပ်ဖြည့်တဲ့ ပုံစံ — ဒါကို Chapter 17 မှာ "method overriding + super()" အဖြစ် အသေးစိတ် ပြန်တွေ့ရမယ်။

မှတ်ချက်

super().__init__(name, age) လို့ အတိုရေးတာ Python 3 ရဲ့ ပုံစံပါ။ Python 2 တုန်းက super(Employee, self).__init__(name, age) လို့ အရှည်ရေးရတယ် — အခုခေတ် code တွေမှာ အတိုပုံစံပဲ သုံးတယ်။ အဓိပ္ပာယ်တူတူပဲ။

မှတ်ချက်

တကယ်တော့ Python class တိုင်းဟာ object ဆိုတဲ့ အခြေခံအကျဆုံး class ဆီက အလိုအလျောက် အမွေခံထားပြီးသား — class Person: လို့ ရေးတာနဲ့ class Person(object): လို့ ရေးတာ အတူတူပဲ။ ဒါကြောင့် isinstance(e, object) က class တိုင်းအတွက် True ထွက်တယ်။ MRO list ရဲ့ နောက်ဆုံးမှာ <class 'object'> ပါတာ ဒါကြောင့်ပါ။

Reference

Inheritance ကို ဘယ်အချိန်သုံးသင့်လဲ

Inheritance က အစွမ်းထက်ပေမယ့် နေရာတိုင်းသုံးရမယ့် အရာ မဟုတ်ဘူး။ စည်းမျဉ်းအတိုချုပ် — "is-a" ဆက်နွယ်မှု ရှိမှ သုံး။ Manager is an Employee — မှန်တယ်။ Car is a Vehicle — မှန်တယ်။ ဒါပေမယ့် Car is an Engine လို့ ပြောလို့မရဘူး — ကားမှာ အင်ဂျင် ပါတာ (has-a)၊ ကားကိုယ်တိုင် အင်ဂျင် ဖြစ်တာ မဟုတ်ဘူး။ အဲဒီလို has-a ဆက်နွယ်မှုအတွက်တော့ inheritance အစား attribute အဖြစ် ထည့်သုံးတယ် (self.engine = Engine())။ ဥပမာ — SavingsAccount is a BankAccount (inheritance မှန်တယ်)၊ ဒါပေမယ့် BankAccount has a TransactionHistory (attribute အဖြစ် ထည့်ရမယ်)။ Inheritance ကို အလွဲသုံးစားလုပ်ရင် class တွေ ရှုပ်ထွေးကုန်ပြီး နောင်မှာ ပြင်ရခက်မယ်။

Mini Project: Employee Management System

အခု inheritance အမျိုးအစားတွေကို တစ်ခုတည်း ပေါင်းသုံးထားတဲ့ လက်တွေ့ project ငယ်တစ်ခု ကြည့်ရအောင် — ဝန်ထမ်းအမျိုးအစားအလိုက် စီမံတဲ့ စနစ်။

ဖွဲ့စည်းပုံက ဒီလို —

  • Person → အခြေခံ class
  • Employee(Person) → single inheritance
  • Manager(Employee) → hierarchical inheritance
  • RemoteEmployee(Employee) → hierarchical inheritance
  • RemoteManager(RemoteEmployee, Manager) → multiple inheritance
# Base Class
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def display_info(self):
        print(f"Name: {self.name}, Age: {self.age}")


# Single Inheritance
class Employee(Person):
    def __init__(self, name, age, emp_id, salary):
        super().__init__(name, age)
        self.emp_id = emp_id
        self.salary = salary

    def display_employee(self):
        self.display_info()
        print(f"Employee ID: {self.emp_id}, Salary: ${self.salary}")

    def annual_salary(self):
        return self.salary * 12


# Hierarchical Inheritance
class Manager(Employee):
    def __init__(self, name, age, emp_id, salary, department):
        super().__init__(name, age, emp_id, salary)
        self.department = department

    def approve_leave(self, employee_name):
        print(f"{self.name} approved leave for {employee_name}.")

    def bonus(self):
        return self.salary * 0.2

    def display_manager(self):
        self.display_employee()
        print(f"Department: {self.department}")


# Hierarchical Inheritance (another branch)
class RemoteEmployee(Employee):
    def __init__(self, name, age, emp_id, salary, city):
        super().__init__(name, age, emp_id, salary)
        self.city = city

    def check_in(self):
        print(f"{self.name} checked in remotely from {self.city}.")


# Multiple Inheritance
class RemoteManager(RemoteEmployee, Manager):
    def __init__(self, name, age, emp_id, salary, city, department):
        Employee.__init__(self, name, age, emp_id, salary)
        self.city = city
        self.department = department

    def display_remote_manager(self):
        self.display_manager()
        print(f"City: {self.city}")


print("=== Manager ===")
mgr = Manager("Daw Hla", 42, "M1001", 8000, "Sales")
mgr.display_manager()
print(f"Annual salary: ${mgr.annual_salary()}")
print(f"Bonus: ${mgr.bonus()}")
mgr.approve_leave("Ko Min")

print("\n=== Remote Employee ===")
re = RemoteEmployee("Ma Nyein", 28, "E2001", 4500, "Mandalay")
re.display_employee()
re.check_in()

print("\n=== Remote Manager ===")
rm = RemoteManager("U Ba", 45, "M3001", 9000, "Yangon", "IT")
rm.display_remote_manager()
rm.approve_leave("Ma Nyein")
rm.check_in()
=== Manager ===
Name: Daw Hla, Age: 42
Employee ID: M1001, Salary: $8000
Department: Sales
Annual salary: $96000
Bonus: $1600.0
Daw Hla approved leave for Ko Min.

=== Remote Employee ===
Name: Ma Nyein, Age: 28
Employee ID: E2001, Salary: $4500
Ma Nyein checked in remotely from Mandalay.

=== Remote Manager ===
Name: U Ba, Age: 45
Employee ID: M3001, Salary: $9000
Department: IT
City: Yangon
U Ba approved leave for Ma Nyein.
U Ba checked in remotely from Yangon.

RemoteManager က RemoteEmployee ဆီက check_in() (ဘယ်မြို့ကနေ အလုပ်လုပ်လဲ) နဲ့ Manager ဆီက approve_leave() (ခွင့်ပြုချက်) နှစ်ခုလုံး ရထားတယ် — multiple inheritance ရဲ့ အစွမ်းပဲ။

Employee Management System: inheritance in layers Person Employee Manager RemoteEmployee RemoteManager multiple inheritance: RemoteManager gets both parents
Employee Management System ရဲ့ inheritance ပုံ

မှတ်ချက်

RemoteManager.__init__ မှာ super() chain အစား Employee ရဲ့ __init__ ကို တစ်ခါတည်း တိုက်ရိုက်ခေါ်ပြီး city/department ကို ကိုယ်တိုင်ဖြည့်ထားတယ်။ Multiple inheritance မှာ super() chain က MRO အတိုင်း လှည့်ပတ်သွားတတ်လို့ (ဥပမာ — RemoteEmployee ရဲ့ super().__init__() က Manager.__init__ ဆီ ရောက်သွားနိုင်တယ်) parameter မတူညီတဲ့ parent တွေအတွက် ဒီနည်းက ရှင်းလင်းပြီး အမှားကင်းတယ်။

Reference

အနှစ်ချုပ်

ဒီအခန်းမှာ inheritance ရဲ့ ပုံစံ ၄ မျိုးလုံး လေ့လာခဲ့ပြီးပြီ — single, multilevel, hierarchical, multiple — နဲ့ super() သုံးပုံ၊ MRO သဘောတရားပါ။ အရေးအကြီးဆုံးကတော့ inheritance ရဲ့ ရည်ရွယ်ချက်ကို မှတ်ထားဖို့ပဲ — code ထပ်ခါရေးစရာ မလိုဘဲ ပြန်သုံးနိုင်ဖို့ (code reuse)။ ဒါပေမယ့် "is-a" ဆက်နွယ်မှုရှိမှသာ သုံးရမယ် ဆိုတဲ့ စည်းကမ်းကိုလည်း မမေ့ပါနဲ့။ နောက်အခန်းမှာ inheritance နဲ့ တွဲဖက်ပြီး အစွမ်းထက်တဲ့ polymorphism ကို လေ့လာမယ်။

  • Inheritance ဆိုတာ child class က parent class ဆီက attribute နဲ့ method တွေကို အမွေဆက်ခံတာ — ရည်ရွယ်ချက်က code reuse။
  • Parent class ကို superclass၊ child class ကို subclass လို့လည်း ခေါ်တယ်။ Syntax: class Child(Parent):။
  • Single — parent တစ်ခုတည်းဆီက (ဥပမာ Cat(Animal))။
  • Multilevel — ဆင့်ကဲဆက်ခံတာ (Animal → Bird → Eagle)။
  • Hierarchical — parent တစ်ခုတည်းကနေ child အများအပြား (Fish, Sparrow တို့ Animal ဆီက)။
  • Multiple — parent တစ်ခုထက်ပိုပြီး (Child(Father, Mother))။ နာမည်တူ method ရှိရင် MRO အရ ဘယ်ဘက်အကျဆုံး parent က အနိုင်ရတယ်။
  • Child ရဲ့ __init__ ရေးတိုင်း super().__init__() နဲ့ parent ရဲ့ constructor ကို ခေါ်ဖို့ မမေ့ပါနဲ့။
  • "is-a" ဆက်နွယ်မှုရှိမှ inheritance သုံး — has-a ဆက်နွယ်မှုအတွက်တော့ attribute အဖြစ် ထည့်သုံးပါ။

ဒီအနှစ်ချုပ်ကို ပြန်ဖတ်ပြီး တစ်ချက်ချင်းစီ ကိုယ့်ဘာသာ ဥပမာနဲ့ ရှင်းပြနိုင်ရင် inheritance ကျွမ်းကျင်ပြီ — မရှင်းသေးတဲ့ အချက်ကို အခန်းထဲ ပြန်သွားဖတ်ပါ။

အမှားများတတ်တဲ့ အချက်များ

  1. super().__init__() မေ့တာ — parent က သတ်မှတ်ပေးတဲ့ attribute တွေ ပျောက်ပြီး AttributeError တက်မယ်။
  2. MRO ကို မေ့တာ — multiple inheritance မှာ class Child(Father, Mother) ဆို Father က အရင်ရှာခံရတယ်။ အစဉ်မှားရင် မမျှော်လင့်တဲ့ method အလုပ်လုပ်မယ်။
  3. Inheritance အလွဲသုံးတာ — ဆက်နွယ်မှုမရှိတဲ့ class တွေကို အတင်း အမွေဆက်ခံခိုင်းရင် code ရှုပ်ထွေးကုန်မယ်။ "is-a" စစ်ဆေးမှုကို အမြဲ လုပ်ပါ။
  4. Parent နာမည် စာလုံးပေါင်းမှားတာ — class Cat(Anima1): လို့ မှားရေးမိရင် NameError တက်မယ်။

လေ့ကျင့်ခန်းများ

အောက်က လေ့ကျင့်ခန်းတွေကို ကိုယ်တိုင် အရင်ကြိုးစားရေးကြည့်ပါ — မှားမှာကို မကြောက်ပါနဲ့၊ မှားမှ သင်ယူရတာ။

၁။ Vehicle (parent) class မှာ brand attribute နဲ့ start() method ("Engine started") ရေးပါ။ Car(Vehicle) child class က honk() method ("Beep!") ထပ်ဖြည့်ပါ။ Car object ထုတ်ပြီး method နှစ်ခုလုံး ခေါ်ပြပါ။ (Single inheritance)

၂။ Grandparent → Parent → Child ဆိုပြီး multilevel inheritance နဲ့ ရေးပါ။ တစ်ခုချင်းစီမှာ ကိုယ်ပိုင် method တစ်ခု (blessing(), advice(), dream()) ထည့်ပြီး Child object ကနေ ၃ ခုလုံး ခေါ်ပြပါ။

၃။ Shape parent class ကနေ Circle နဲ့ Square တို့ hierarchical inheritance နဲ့ ဆင်းသက်ပါစေ။ Circle မှာ area() (pi * r * r), Square မှာ area() (side * side) ကိုယ်စီ ရေးပါ။ (ဒါက method overriding ရဲ့ အစလည်း ဖြစ်တယ် — Chapter 17 မှာ ဆက်သင်မယ်။)

၄။ Flyer class (fly() method) နဲ့ Swimmer class (swim() method) နှစ်ခုကနေ Duck(Flyer, Swimmer) ကို multiple inheritance နဲ့ ရေးပါ။ Duck object က method နှစ်ခုလုံး သုံးနိုင်တာ ပြပါ။

၅။ (စိန်ခေါ်မှု) — Person (name, age) ကနေ Teacher(Person) (subject, salary) ကို inheritance နဲ့ ရေးပါ။ Teacher ရဲ့ __init__ မှာ super().__init__() သုံးပြီး yearly_income() (salary * 12 + bonus 500000) method ထည့်ပါ။