Devfavor

Back

OOP คืออะไร — เข้าใจ 3 แกนหลัก Encapsulation, Inheritance, PolymorphismBlur image

ถ้าเคยเปิด codebase ใหม่แล้วเจอ class เต็มไปหมด แล้วงงว่า “อันนี้ extend มาจากอันไหน? ทำไม method ชื่อเดียวกันถึงอยู่ต่าง class ได้?” — นั่นคือสัญญาณว่า OOP กำลังทำงานอยู่ แต่ละหลักการแก้ปัญหาคนละอย่าง และเข้าใจแยกกันได้ชัดกว่า

Object-Oriented Programming หรือ OOP ไม่ได้แค่เรื่อง “เขียนโค้ดใน class” แต่คือชุดแนวคิดที่ช่วยจัดระเบียบโปรแกรมขนาดใหญ่ให้ดูแลได้จริง หลักการหลักของ OOP มีสี่ข้อ — Encapsulation, Inheritance, Polymorphism และ Abstraction สามข้อแรกคือสิ่งที่จะเจอบ่อยที่สุดในเกือบทุกภาษา


🔒 Encapsulation — ซ่อนข้างใน เปิดแค่ที่จำเป็น#

ลองนึกถึง ATM ตู้นี้รู้วิธีตรวจยอด คำนวณเงิน เชื่อมระบบธนาคาร แต่เราในฐานะผู้ใช้แค่กดถอนเงินแล้วรับเงินออกมา ไม่รู้ว่าข้างในทำอะไรบ้าง — นั่นคือ Encapsulation

Encapsulation คือการซ่อนสถานะภายในของ object และเปิดเผยเฉพาะ interface สาธารณะที่จำเป็น

ใน code ทำได้ผ่าน access modifiers:

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # ตั้งใจให้เป็นข้อมูลภายใน ไม่ให้แตะจากข้างนอกตรง ๆ

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount

    def get_balance(self):
        return self.__balance
python

__balance ตั้งใจให้เป็นข้อมูลภายในของ object ไม่ใช่สิ่งที่โค้ดข้างนอกควรไปอ่านหรือแก้ตรง ๆ ใครอยากรู้ยอดให้เรียกผ่าน get_balance() แทน — นี่คือหัวใจของ Encapsulation: ภายนอกคุยกับ object ผ่าน method สาธารณะ ไม่ใช่ไปยุ่งกับ state ข้างในเอง

Encapsulation แก้ปัญหาอะไร?#

  • ป้องกัน accidental modification — ถ้าทุกคนเข้าถึง field ตรง ๆ ได้ โค้ดส่วนใดก็อาจเปลี่ยนค่าโดยไม่ตั้งใจ
  • เปลี่ยน internal implementation ได้โดยไม่กระทบภายนอก — อยากเปลี่ยนวิธีเก็บ balance จาก float เป็น Decimal ก็ทำได้ ตราบใดที่ get_balance() ยังคืนค่าเดิม
  • แต่ละ class รับผิดชอบ state ของตัวเอง — ไม่มี class ไหนแอบไปแก้ state ของ class อื่นได้โดยตรง

หมายเหตุ: Abstraction ≠ Encapsulation#

คนมักสับสนสองอันนี้ ตอบสั้น ๆ คือ:

  • Abstraction — ซ่อนรายละเอียดที่ไม่จำเป็น เปิดเฉพาะ interface ที่ใช้งาน
  • Encapsulation — ควบคุมการเข้าถึงข้อมูลภายใน object ผ่าน access control

Abstraction พูดถึงระดับ design ว่า interface ควรมีหน้าตาอย่างไร, Encapsulation พูดถึงกลไกที่ปกป้อง state ภายในไม่ให้ถูกเข้าถึงโดยตรง


Encapsulation ช่วยให้แต่ละ class ดูแลตัวเองได้ แต่ถ้า class หลายตัวมีโครงสร้างคล้ายกัน จะเริ่มใหม่ตั้งแต่ต้นทุกครั้งหรือ? นั่นคือที่มาของ Inheritance

🧬 Inheritance — รับมรดก ไม่ต้อง copy#

ถ้ามีระบบที่ต้องจัดการทั้ง Student และ Professor ทั้งคู่มีชื่อ มีอีเมล มี method greet() เหมือนกัน จะ copy โค้ดไปแปะทั้งสอง class ก็ทำได้ — แต่พอต้องแก้ greet() ต้องแก้สองที่ แล้วก็มักลืมแก้อีกอัน

Inheritance ช่วยให้ subclass รับ properties และ methods จาก superclass ได้โดยไม่ต้อง copy code

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

    def greet(self):
        return f"สวัสดี ฉันชื่อ {self.name}"

class Student(Person):
    def __init__(self, name, email, student_id):
        super().__init__(name, email)
        self.student_id = student_id

class Professor(Person):
    def __init__(self, name, email, department):
        super().__init__(name, email)
        self.department = department
python

Student และ Professor ต่างก็ได้ name, email และ greet() มาจาก Person โดยอัตโนมัติ แต่ละ class เพิ่มเฉพาะสิ่งที่ต่างกัน

ข้อดี#

  • Code reuse — logic ที่ใช้ร่วมกันอยู่ที่เดียว แก้ที่เดียวกระทบทุก subclass
  • Hierarchy ที่เป็นธรรมชาติ — Student เป็น Person ประเภทหนึ่ง ความสัมพันธ์แบบนี้ map ได้ดีใน code

ข้อควรระวัง#

Inheritance ที่ลึกเกินไป (หลาย level) ทำให้ trace โค้ดยาก บางครั้ง composition (การใส่ object เป็น field แทนการ inherit) เหมาะกว่า โดยเฉพาะเมื่อ relationship ไม่ได้เป็น “A เป็น B” อย่างชัดเจน เช่น Car กับ Engine — Car ไม่ได้ “เป็น” Engine แต่ Car “มี” Engine จึงเหมาะกับ composition มากกว่า


🎭 Polymorphism — ชื่อเดียว หลายรูปแบบ#

“Polymorphism” มาจากภาษากรีก แปลตรงตัวว่า “หลายรูปแบบ” ในโลก software หมายถึง object ต่างประเภทสามารถตอบสนองต่อ method ชื่อเดียวกันได้ โดยแต่ละประเภทมี behavior เป็นของตัวเอง ลองดูตัวอย่างนี้:

class Animal:
    def speak(self):
        return "..."

class Dog(Animal):
    def speak(self):
        return "โฮ่ง!"

class Cat(Animal):
    def speak(self):
        return "เมียว~"

animals = [Dog(), Cat(), Dog()]
for animal in animals:
    print(animal.speak())
# โฮ่ง!
# เมียว~
# โฮ่ง!
python

แม้ลูป iterate ผ่าน Animal แต่แต่ละตัวเรียก speak() ของตัวเองได้ถูก — นี่คือ Polymorphism: method ชื่อเดียวกัน ทำงานต่างกันในแต่ละ class ตัวอย่างนี้เป็น runtime polymorphism แบบ method overriding

สองประเภทหลัก#

ประเภทเรียกว่าresolve เมื่อไหร่ตัวอย่าง
Compile-timeOverloadingตอน compilefunction ชื่อเดียว parameter ต่างกัน
RuntimeOverridingตอน runsubclass override method ของ superclass

ใน C# จะเห็น keyword virtual ที่ base class method และ override ใน derived class — เป็น syntax ที่บังคับให้ประกาศชัดเจนว่าตั้งใจ override:

class Animal {
    public virtual string Speak() => "...";
}

class Dog : Animal {
    public override string Speak() => "โฮ่ง!";
}
csharp

ทำไม Polymorphism ถึงมีประโยชน์#

สมมติมีระบบ payment ที่รองรับทั้ง Credit Card, PromptPay และ Crypto ถ้าไม่มี polymorphism ต้องเขียน if/else ยาวเพื่อเช็คประเภทแล้วเรียก method ที่ถูกต้อง — แต่ถ้าทุก payment type implement interface เดียวกัน (process_payment()) โค้ดส่วนกลางเรียกได้เลยโดยไม่สนว่าข้างในคือประเภทไหน

เพิ่ม payment type ใหม่ก็แค่เพิ่ม class ใหม่ ไม่ต้องแตะโค้ดส่วนกลาง


🤝 สามแนวคิดนี้ทำงานร่วมกัน#

ในชีวิตจริง ทั้งสามแนวคิดนี้ไม่ได้ใช้แยกกัน:

  • Encapsulation ทำให้แต่ละ class ดูแล state ของตัวเองได้ ไม่ให้ภายนอกยุ่ง
  • Inheritance ทำให้แชร์โครงสร้างร่วมกันโดยไม่ copy
  • Polymorphism ทำให้ใช้ interface เดียวกับ object หลายประเภท โดยแต่ละประเภทมี behavior ของตัวเอง

ระบบที่ออกแบบดีมักใช้ทั้งสามอย่างประกอบกัน เช่น Payment เป็น abstract class (inheritance + polymorphism) ที่ซ่อน internal logic ของแต่ละ provider ไว้ข้างใน (encapsulation)


⚖️ เมื่อไหร่ควรใช้ และเมื่อไหร่ไม่ควรใช้ OOP#

OOP เหมาะกับระบบที่:

  • มี entity หลายประเภทที่มีความสัมพันธ์กัน เช่น User, Admin, Guest
  • มี behavior ที่ต้อง reuse ข้าม entity หลายตัว
  • ต้องการขยาย (extend) ในอนาคตโดยไม่แตะโค้ดเดิม

OOP อาจไม่ใช่ทางเลือกที่ดีที่สุดเมื่อ:

  • งานเป็น data transformation ตรง ๆ เช่น ETL pipeline, script ง่าย ๆ — functional style อาจสะอาดกว่า
  • ทีมยังไม่คุ้นเคย การฝืนใช้ OOP โดยออกแบบไม่ดีอาจทำให้เกิด hierarchy ที่ซับซ้อนเกินจำเป็น

ถ้าอ่านมาถึงตรงนี้แล้วรู้สึกว่า “โอ้ นี่คือสิ่งที่เจอใน codebase ทุกวัน แต่ไม่รู้ชื่อ” — ยินดีต้อนรับ ตอนนี้คุณรู้ชื่อแนวคิดพวกนี้แล้ว และพอเห็นภาพสามหลักการนี้ชัดขึ้น การอ่าน design patterns ก็จะเริ่มชัดและสมเหตุสมผลขึ้นเอง

สามแนวคิดนี้เป็นฐานของ design patterns หลายอย่างที่ใช้กันจริงใน production เช่น Strategy, Template Method, Factory — ซึ่งล้วนยืมไอเดียจาก polymorphism และ inheritance ไปต่อยอด

ลองเปิด codebase ที่ใช้อยู่แล้วลอง trace ว่า pattern ไหนซ่อน inheritance หรือ polymorphism ไว้ข้างใน — คำตอบมักอยู่ใกล้กว่าที่คิด

😎 ☕

Code, coffee, and calm — the holy trinity of a good day. ☕

OOP คืออะไร — เข้าใจ 3 แกนหลัก Encapsulation, Inheritance, Polymorphism
Author Coffee Stack
Published at 13 มิถุนายน 2026