Notes & software courses · Free to learn
Aph's Blog
On this page

4 เสาหลักของ OOP

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

Encapsulation, Inheritance, Polymorphism, Abstraction — แนวคิดหลักที่มักถูกถามในสัมภาษณ์ พร้อมตัวอย่าง

OOP มีแนวคิดหลัก 4 อย่างที่เรียกว่า "4 เสาหลัก" (four pillars) เป็นคำถามสัมภาษณ์ยอดฮิต เราจะดูทีละข้อพร้อมตัวอย่างโค้ดที่เข้าใจง่าย

1) Encapsulation — ห่อหุ้มข้อมูล

รวมข้อมูลและ method ที่เกี่ยวข้องไว้ด้วยกัน และซ่อนรายละเอียดภายในไม่ให้ภายนอกแก้ตรง ๆ บังคับให้แก้ผ่าน method ที่ควบคุมได้ ใน Python ใช้ขีดล่าง _ (บอกว่า "ภายใน") หรือ __ (ซ่อนแรงขึ้น) นำหน้าชื่อ

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) มาใช้ต่อได้ ไม่ต้องเขียนซ้ำ และเพิ่มหรือแก้เฉพาะส่วนที่ต่าง ช่วยลดโค้ดซ้ำซ้อนมาก

python
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)
python
# เรียก method ของแม่ด้วย super()
class Puppy(Dog):
    def __init__(self, name, age):
        super().__init__(name)   # เรียก __init__ ของแม่
        self.age = age

3) Polymorphism — หลายรูปแบบ

object ต่างชนิดตอบสนอง method ชื่อเดียวกันได้ในแบบของตัวเอง ทำให้เขียนโค้ดที่ทำงานกับหลายชนิดได้โดยไม่ต้องแยกเคส

python
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())   # โฮ่ง เมี้ยว มอ โฮ่ง
ทำไม polymorphism ดี

ถ้าไม่มี เราต้องเขียน if แยกทุกชนิด (ถ้าเป็นหมา...ถ้าเป็นแมว...) แต่ polymorphism ให้เราเรียก a.sound() เหมือนกันหมด เพิ่มสัตว์ชนิดใหม่ก็ไม่ต้องแก้ loop เดิม

4) Abstraction — ซ่อนความซับซ้อน

เปิดเผยเฉพาะสิ่งที่จำเป็นต้องใช้ ซ่อนรายละเอียดยุ่งยากไว้ภายใน เหมือนขับรถโดยไม่ต้องรู้ว่าเครื่องยนต์ทำงานอย่างไร แค่รู้ว่าเหยียบคันเร่งแล้วไป method ที่ผู้ใช้เรียกคือ "หน้าบ้าน" ส่วนตรรกะซับซ้อนซ่อนอยู่ "หลังบ้าน"

python
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
Inheritanceclass ลูกรับคุณสมบัติจาก class แม่ ลดโค้ดซ้ำ
Polymorphismobject ต่างชนิดตอบสนอง method ชื่อเดียวกันในแบบตัวเอง
Abstractionซ่อนความซับซ้อน เปิดเผยเฉพาะที่จำเป็น
แบบฝึกหัด

1) ทำ BankAccount ที่ซ่อน balance และฝาก-ถอนผ่าน method (ห้ามถอนเกิน) 2) สร้าง Animal แม่ แล้วให้ Dog, Bird สืบทอด พร้อม override sound() 3) เขียนฟังก์ชันรับลิสต์ของรูปทรง (Circle, Rectangle) แล้วเรียก area() ของแต่ละตัว (polymorphism) 4) ใช้ super() เรียก __init__ ของแม่ใน subclass