การเขียนโปรแกรมเชิงวัตถุใน Python
OOP จัดโปรแกรมรอบออบเจ็กต์ที่มีสถานะและเปิดเผยพฤติกรรมผ่านอินเทอร์เฟซที่ชัดเจน
การเขียนโปรแกรมเชิงวัตถุใน Python คืออะไร?
OOP สร้างแบบจำลองระบบเป็นออบเจ็กต์ที่ทำงานร่วมกัน แต่ละออบเจ็กต์รวมสถานะและการทำงานที่อนุญาต ทำให้ความรับผิดชอบในโปรแกรมใหญ่ชัดเจน
หลักสำคัญสี่ข้อของ OOP
- Encapsulation: รวมสถานะและพฤติกรรมและควบคุมการเข้าถึง
- Abstraction: แสดงอินเทอร์เฟซที่จำเป็นและซ่อนรายละเอียด
- Inheritance: สร้างคลาสเฉพาะเมื่อมีความสัมพันธ์ is-a จริง
- Polymorphism: ใช้การทำงานเดียวกันกับหลายชนิดโดยแต่ละชนิดมีพฤติกรรมเหมาะสม
การออกแบบตัวอย่าง
- BankAccount เป็นเจ้าของยอดเงินและตรวจสอบการฝาก
- SavingsAccount ใช้สัญญาของคลาสฐาน
- SavingsAccount override month_end เพื่อเพิ่มดอกเบี้ย
- ลูปจัดการทุกบัญชีผ่านอินเทอร์เฟซเดียวกัน
ตัวอย่างพื้นฐาน
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self._balance = float(balance)
@property
def balance(self):
return self._balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit must be positive")
self._balance += amount
def month_end(self):
return "No interest"
class SavingsAccount(BankAccount):
def __init__(self, owner, balance, interest_rate):
super().__init__(owner, balance)
self.interest_rate = interest_rate
def month_end(self):
self._balance *= 1 + self.interest_rate
return "Interest applied"
accounts = [
BankAccount("Ada", 100),
SavingsAccount("Lin", 200, 0.05),
]
accounts[0].deposit(50)
for account in accounts:
status = account.month_end()
print(f"{account.owner}: {account.balance:.2f} ({status})")
ผลลัพธ์ที่คาดหวัง
Ada: 150.00 (No interest)
Lin: 210.00 (Interest applied)
หลัก OOP ทั้งสี่ในการใช้งานจริง
ตัวอย่างเหล่านี้แสดงวิธีที่ Python ใช้ encapsulation, abstraction, inheritance และ polymorphism ในโค้ดทั่วไป
Encapsulation
รวมสถานะและพฤติกรรมและควบคุมการเข้าถึง
class BankAccount:
def __init__(self, balance=0):
# Double underscores prevent accidental direct access.
self.__balance = balance
@property
def balance(self):
# Expose read access without exposing mutation.
return self.__balance
def deposit(self, amount):
# Keep validation next to the state it protects.
if amount <= 0:
raise ValueError("Amount must be positive")
self.__balance += amount
account = BankAccount(100)
account.deposit(50)
print(account.balance) # 150
Abstraction
แสดงอินเทอร์เฟซที่จำเป็นและซ่อนรายละเอียด
from abc import ABC, abstractmethod
class PaymentMethod(ABC):
@abstractmethod
def pay(self, amount):
# Callers know what pay does, not how each provider does it.
pass
class CreditCard(PaymentMethod):
def pay(self, amount):
# The concrete class hides its payment implementation.
return f"Paid ${amount:.2f} by card"
payment = CreditCard()
print(payment.pay(25))
Inheritance
สร้างคลาสเฉพาะเมื่อมีความสัมพันธ์ is-a จริง
class Employee:
def __init__(self, name):
self.name = name
def describe(self):
return self.name
class Developer(Employee):
def __init__(self, name, language):
# Reuse initialization from the parent class.
super().__init__(name)
self.language = language
def describe(self):
# Extend inherited behavior instead of duplicating it.
return f"{super().describe()} writes {self.language}"
print(Developer("Ada", "Python").describe())
Polymorphism
ใช้การทำงานเดียวกันกับหลายชนิดโดยแต่ละชนิดมีพฤติกรรมเหมาะสม
class EmailNotification:
def send(self, message):
return f"Email: {message}"
class SmsNotification:
def send(self, message):
return f"SMS: {message}"
def notify(channels, message):
for channel in channels:
# The same call selects behavior from each concrete object.
print(channel.send(message))
channels = [EmailNotification(), SmsNotification()]
notify(channels, "Order shipped")
หลักการทำงาน
BankAccount ห่อหุ้มยอดเงิน SavingsAccount สืบทอดอินเทอร์เฟซและ override month_end ลูปใช้ออบเจ็กต์ทั้งสองแบบเดียวกันและ Python เลือกเมธอดขณะรัน
เปลี่ยนค่าและรันโปรแกรมด้วย คอมไพเลอร์ Python ออนไลน์ของ CodeUtility โดยไม่ต้องติดตั้ง Python
แบบฝึกหัด
ลองเปลี่ยน input และทดสอบกรณีขอบก่อนใช้ชุดข้อมูลที่ใหญ่ขึ้น
- คาดเดา output ก่อนรัน
- รองรับ input ว่างหรือไม่ถูกต้อง
- แยก logic เป็นฟังก์ชันและเพิ่ม test case