On this page
4 เสาหลักของ OOP
Encapsulation, Inheritance, Polymorphism, Abstraction — แนวคิดหลักที่มักถูกถามในสัมภาษณ์ พร้อมตัวอย่าง
OOP มีแนวคิดหลัก 4 อย่างที่เรียกว่า "4 เสาหลัก" (four pillars) เป็นคำถามสัมภาษณ์ยอดฮิต เราจะดูทีละข้อพร้อมตัวอย่างโค้ดที่เข้าใจง่าย
1) Encapsulation — ห่อหุ้มข้อมูล
รวมข้อมูลและ method ที่เกี่ยวข้องไว้ด้วยกัน และซ่อนรายละเอียดภายในไม่ให้ภายนอกแก้ตรง ๆ บังคับให้แก้ผ่าน method ที่ควบคุมได้ ใน Python ใช้ขีดล่าง _ (บอกว่า "ภายใน") หรือ __ (ซ่อนแรงขึ้น) นำหน้าชื่อ
class BankAccount:
def __init__(self):
self.__balance = 0 # __ = private (ซ่อน)
def deposit(self, amount):
if amount > 0: # ควบคุมเงื่อนไขผ่าน method
self.__balance += amount
def get_balance(self):
return self.__balance
acc = BankAccount()
acc.deposit(1000)
acc.deposit(-50) # ถูกปฏิเสธเพราะติดลบ
print(acc.get_balance()) # 1000
# acc.__balance = 999999 # แก้ตรง ๆ ไม่ได้ถ้าใครก็แก้ balance ได้ตรง ๆ อาจตั้งเป็นค่าติดลบหรือค่าที่ผิดกติกา การบังคับให้ผ่าน deposit/withdraw ทำให้เราควบคุมเงื่อนไขได้ ข้อมูลจึงอยู่ในสถานะที่ถูกต้องเสมอ
2) Inheritance — การสืบทอด
class ลูก (subclass) รับคุณสมบัติจาก class แม่ (superclass) มาใช้ต่อได้ ไม่ต้องเขียนซ้ำ และเพิ่มหรือแก้เฉพาะส่วนที่ต่าง ช่วยลดโค้ดซ้ำซ้อนมาก
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
return f"{self.name} กำลังกิน"
class Cat(Animal): # Cat สืบทอดจาก Animal
def meow(self): # เพิ่ม method ของตัวเอง
return f"{self.name} ร้อง: เมี้ยว"
class Dog(Animal):
def eat(self): # เขียนทับ (override) ของแม่
return f"{self.name} กินอย่างตะกละ"
c = Cat("มะลิ")
print(c.eat()) # มะลิ กำลังกิน (ได้จาก Animal)
print(c.meow()) # มะลิ ร้อง: เมี้ยว
print(Dog("ไข่ดาว").eat()) # ไข่ดาว กินอย่างตะกละ (override)# เรียก method ของแม่ด้วย super()
class Puppy(Dog):
def __init__(self, name, age):
super().__init__(name) # เรียก __init__ ของแม่
self.age = age3) Polymorphism — หลายรูปแบบ
object ต่างชนิดตอบสนอง method ชื่อเดียวกันได้ในแบบของตัวเอง ทำให้เขียนโค้ดที่ทำงานกับหลายชนิดได้โดยไม่ต้องแยกเคส
class Dog:
def sound(self):
return "โฮ่ง"
class Cat:
def sound(self):
return "เมี้ยว"
class Cow:
def sound(self):
return "มอ"
# ฟังก์ชันเดียว ใช้ได้กับทุก object ที่มี sound()
animals = [Dog(), Cat(), Cow(), Dog()]
for a in animals:
print(a.sound()) # โฮ่ง เมี้ยว มอ โฮ่งถ้าไม่มี เราต้องเขียน if แยกทุกชนิด (ถ้าเป็นหมา...ถ้าเป็นแมว...) แต่ polymorphism ให้เราเรียก a.sound() เหมือนกันหมด เพิ่มสัตว์ชนิดใหม่ก็ไม่ต้องแก้ loop เดิม
4) Abstraction — ซ่อนความซับซ้อน
เปิดเผยเฉพาะสิ่งที่จำเป็นต้องใช้ ซ่อนรายละเอียดยุ่งยากไว้ภายใน เหมือนขับรถโดยไม่ต้องรู้ว่าเครื่องยนต์ทำงานอย่างไร แค่รู้ว่าเหยียบคันเร่งแล้วไป method ที่ผู้ใช้เรียกคือ "หน้าบ้าน" ส่วนตรรกะซับซ้อนซ่อนอยู่ "หลังบ้าน"
class CoffeeMachine:
def make_coffee(self): # ผู้ใช้เรียกแค่อันนี้
self.__boil_water()
self.__grind_beans()
return "กาแฟพร้อมแล้ว"
def __boil_water(self): # รายละเอียดภายใน ซ่อนไว้
pass
def __grind_beans(self):
pass
print(CoffeeMachine().make_coffee()) # กาแฟพร้อมแล้วสรุป 4 เสาหลัก
| เสาหลัก | ความหมายสั้น ๆ |
|---|---|
| Encapsulation | ห่อหุ้ม+ซ่อนข้อมูล ควบคุมการเข้าถึงผ่าน method |
| Inheritance | class ลูกรับคุณสมบัติจาก class แม่ ลดโค้ดซ้ำ |
| Polymorphism | object ต่างชนิดตอบสนอง method ชื่อเดียวกันในแบบตัวเอง |
| Abstraction | ซ่อนความซับซ้อน เปิดเผยเฉพาะที่จำเป็น |
1) ทำ BankAccount ที่ซ่อน balance และฝาก-ถอนผ่าน method (ห้ามถอนเกิน) 2) สร้าง Animal แม่ แล้วให้ Dog, Bird สืบทอด พร้อม override sound() 3) เขียนฟังก์ชันรับลิสต์ของรูปทรง (Circle, Rectangle) แล้วเรียก area() ของแต่ละตัว (polymorphism) 4) ใช้ super() เรียก __init__ ของแม่ใน subclass