目次
1. ภาพรวมของการสืบทอดใน Python
ใน Python การสืบทอด คือกลไกที่คลาสลูกรับช่วงฟังก์ชันการทำงานและแอตทริบิวต์จากคลาสแม่ ซึ่งช่วยเพิ่มความสามารถในการนำโค้ดกลับมาใช้ซ้ำและทำให้การบำรุงรักษามีประสิทธิภาพมากขึ้น เป็นหนึ่งในแนวคิดสำคัญของการเขียนโปรแกรมเชิงวัตถุ (OOP) โดยเฉพาะอย่างยิ่งมีประโยชน์ต่อการพัฒนาระบบขนาดใหญ่และโครงการระยะยาวบทบาทพื้นฐานของการสืบทอด
- การนำโค้ดกลับมาใช้ซ้ำ: ฟังก์ชันการทำงานของคลาสที่เขียนไว้ครั้งเดียวสามารถใช้งานในคลาสอื่นได้ ช่วยหลีกเลี่ยงโค้ดซ้ำซ้อน
- ความง่ายในการบำรุงรักษา: การเปลี่ยนแปลงในคลาสแม่จะสะท้อนถึงคลาสลูกโดยอัตโนมัติ ทำให้การแก้ไขและการขยายความสามารถทำได้อย่างมีประสิทธิภาพ
class ParentClass:
def greet(self):
print("สวัสดี นี่คือคลาสแม่")
class ChildClass(ParentClass):
def greet(self):
print("สวัสดี นี่คือคลาสลูก")
ในตัวอย่างนี้ ChildClass
ได้เขียนทับเมธอดของ ParentClass
เมธอด greet
ถูกโอเวอร์ไรด์ จึงจะแสดงคำทักทายเฉพาะของคลาสลูก2. การสืบทอดแบบเดี่ยวใน Python
การสืบทอดแบบเดี่ยวคือรูปแบบที่มีคลาสลูกหนึ่งคลาสสืบทอดความสามารถมาจากคลาสแม่หนึ่งคลาส นี่เป็นรูปแบบพื้นฐานของการสืบทอดใน Python ซึ่งช่วยคงความเรียบง่ายของโค้ดไว้พร้อมทั้งเพิ่มความสามารถในการขยายต่อได้ไวยากรณ์พื้นฐานและตัวอย่างของการสืบทอดแบบเดี่ยว
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
def describe(self):
print(f"รถคันนี้คือ {self.brand} สี{self.color}.")
class ElectricCar(Car):
def __init__(self, brand, color, battery_size):
super().__init__(brand, color)
self.battery_size = battery_size
def describe_battery(self):
print(f"ความจุแบตเตอรี่คือ {self.battery_size} kWh.")
ในตัวอย่างนี้ คลาสElectricCar
สืบทอดความสามารถของคลาสCar
พร้อมทั้งเพิ่มฟังก์ชันสำหรับอธิบายความจุแบตเตอรี่ ใช้super()
เพื่อเรียกคอนสตรัคเตอร์ของคลาสแม่และกำหนดค่าเริ่มต้นให้กับแอตทริบิวต์ที่ใช้ร่วมกัน (เช่น แบรนด์และสี)
3. การโอเวอร์ไรด์เมธอด
การโอเวอร์ไรด์ คือความสามารถที่คลาสลูกกำหนดนิยามเมธอดของคลาสแม่ขึ้นมาใหม่ได้ ด้วยเหตุนี้ เราจึงสามารถปรับเปลี่ยนการทำงานในคลาสลูกไปพร้อมกับการใช้ประโยชน์จากเมธอดของคลาสแม่ได้ตัวอย่างการโอเวอร์ไรด์
class Animal:
def speak(self):
print("เสียงร้องของสัตว์")
class Dog(Animal):
def speak(self):
print("โฮ่ง โฮ่ง!")
ในตัวอย่างนี้ คลาสDog
ได้โอเวอร์ไรด์เมธอดspeak
ของคลาสAnimal
ด้วยเหตุนี้ อินสแตนซ์ของคลาสDog
จะพิมพ์ว่า「โฮ่ง โฮ่ง」 ในขณะที่อินสแตนซ์ของคลาสAnimal
จะแสดงว่า「เสียงร้องของสัตว์」。4. การสืบทอดหลายทาง
การสืบทอดหลายทางคือกรณีที่คลาสลูกเพียงคลาสเดียวสามารถสืบทอดจากคลาสพ่อแม่หลายคลาสได้ ซึ่งช่วยรวมความสามารถจากคลาสต่างๆ ไว้ในคลาสเดียวได้ แต่ควรระวังเพราะอาจทำให้การใช้งานซับซ้อนขึ้นได้ตัวอย่างและข้อควรระวังของการสืบทอดหลายทาง
class A:
def greet(self):
print("คำทักทายของ A")
class B:
def greet(self):
print("คำทักทายของ B")
class C(A, B):
pass
c = C()
c.greet() # จะแสดง "คำทักทายของ A" (ตาม MRO คลาสแรกจะถูกใช้ก่อน)
ใน Python การเรียกใช้เมธอดของคลาสพ่อแม่ใดจะถูกกำหนดโดยMRO (Method Resolution Order) หากต้องการตรวจสอบลำดับนี้ ให้ใช้ C.mro()
การสืบทอดหลายทางทรงพลัง แต่ควรใช้อย่างระมัดระวัง โดยคำนึงถึงความขัดแย้งระหว่างคลาสพ่อแม่และลำดับของเมธอด
5. ตัวอย่างเชิงปฏิบัติของการใช้การสืบทอด
การสืบทอดมีประโยชน์ในหลายสถานการณ์ของการเขียนโปรแกรมในชีวิตประจำวัน ตัวอย่างเช่น ในระบบจัดการพนักงานขององค์กร การให้คลาสที่มีตำแหน่งงานเฉพาะสืบทอดจากคลาสพนักงานพื้นฐาน จะทำให้สามารถนำโค้ดกลับมาใช้ซ้ำและขยายต่อได้ตัวอย่างระบบจัดการพนักงานแบบใช้งานจริง
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
def fullname(self):
return f'{self.first} {self.last}'
class Manager(Employee):
def __init__(self, first, last, pay, employees=None):
super().__init__(first, last, pay)
self.employees = employees if employees is not None else []
def add_employee(self, employee):
if employee not in self.employees:
self.employees.append(employee)
def print_employees(self):
for emp in self.employees:
print(emp.fullname())
ในตัวอย่างนี้ คลาสManager
สืบทอดจากคลาสEmployee
และเพิ่มความสามารถในการจัดการพนักงาน ขณะที่ยังคงฟังก์ชันทั่วไปของคลาสแม่ไว้ ก็ขยายความสามารถให้สอดคล้องกับตำแหน่งงานเฉพาะ6. แนวปฏิบัติที่ดีที่สุดสำหรับการสืบทอดและการเปรียบเทียบกับคอมโพซิชัน
การสืบทอดนั้นทรงพลังมาก แต่หากใช้มากเกินไปก็มีความเสี่ยงที่โค้ดจะซับซ้อนขึ้น โดยเฉพาะการสืบทอดหลายทางอาจทำให้ความสัมพันธ์ระหว่างคลาสซับซ้อน จึงควรใช้อย่างระมัดระวัง ในกรณีเช่นนี้ แนะนำให้ใช้คอมโพซิชันแทนการสืบทอดตัวอย่างคอมโพซิชัน
คอมโพซิชันคือรูปแบบการออกแบบที่คลาสหนึ่งมีอีกคลาสหนึ่งเป็นส่วนประกอบ (อินสแตนซ์) เพื่อมอบหมายการทำงานclass Engine:
def start(self):
print("เครื่องยนต์เริ่มทำงานแล้ว")
class Car:
def __init__(self, engine):
self.engine = engine
def start(self):
self.engine.start()
engine = Engine()
car = Car(engine)
car.start() # จะแสดง "เครื่องยนต์เริ่มทำงานแล้ว"
ดังที่เห็น วิธีการแชร์การทำงานระหว่างคลาสโดยไม่ใช้การสืบทอดคือคอมโพซิชัน ด้วยการใส่เฉพาะความสามารถที่จำเป็น โค้ดจะยืดหยุ่นมากขึ้นและจัดการได้ง่ายขึ้น。