หัดเขียน OOP ด้วย Python
ไม่ว่าคุณจะเขียนโปรแกรมภาษาอะไรก็ตาม Object Oriented Programming(OOP) จะเป็นสิ่งที่ต้องทำความเข้าใจและใช้งานให้ถูกต้อง ในบทความนี้ผมจะพาคุณไปรู้จักกับ การเขียน OOP ด้วย Python
Class vs Object
สิ่งแรกที่ต้องรู้จักก็คือ Class และ Object ความแตกต่างของ Class และ Object คือ
- Class คือ นิยามที่บอกว่า Object ประเภทนี้มีคุณลักษณะ(property)อย่างไรและมีความสามารถอะไรบ้าง(method)
- Object คือ ตัวละครที่จะนำไปใช้งานในระบบจริงๆ เราจะสร้าง Object ขึ้นมาใช้งาน โดยจะต้องบอกว่า Object นี้เป็น Class ไหน
ตัวอย่าง เช่น เรามี Class ที่ชื่อว่า Duck มี property อยู่ 2 ตัวคือ _sound และ _movement
|
|
สังเกตุว่า function ที่ประกาศอยู่ใน class จะต้องมี parameter ตัวแรกเป็น self ซึ่งจะเหมือนกับ this ในภาษาอื่นๆ
เวลานำ class ไป instantiating(สร้าง Object ขึ้นมาใช้งาน) เราจะเขียนแบบนี้
donald = Duck()
print(donald._sound)
# ตอนเรียก method move ไม่ต้องใส่ self
donald.move()
การใช้งาน Constructor
ใน Python จะมี default constructor มาให้อยู่แล้ว จากตัวอย่างที่แล้ว จะเห็นว่าเราสามารถสร้าง object ขึ้นมาได้เลย โดยที่ไม่ต้องมี constructor ส่วนถ้าคุณต้องการสร้าง constructor ขึ้นมาเองโดยใช้ method init โดยเราจะสามารถใส่ parameters เข้ามาได้แบบนี้
|
|
เราสามารถ รับ parameters หลายๆตัวได้ โดยที่ต้องเปลี่ยน parameters ใน init() เป็น **args และตอนสร้าง object ต้องใส่ชื่อ argument ด้วย(บรรทัดที่ 9)
|
|
Access Modifier
ใน Python จะไม่มี access modifier(public, private) แบบภาษาอื่นๆ เพราะ python ต้องการความง่ายในการเขียน ดังนั้นเราะไม่ได้เขียน getter และ setter เหมือนกับภาษาอื่นๆ แต่เราจะใช้ “_” นำหน้าตัวแปร เช่นเปลี่ยนจาก type เป็น _type แล้วทุกคนที่เขียน python จะรู้กันว่าตัวแปร _type นี้เป็น private ถ้าคุณเรียก _type ตรงๆผลลัพธ์ที่ได้อาจไม่ตรงกับที่คุณคาดคิด
เปลี่ยน method ให้เป็น property ด้วย @Property
เหมือนกับ getter ในภาษาอื่นๆ ใน python เมื่อเราใส่ annotation @Property ไว้บน method ไหน เราจะสามารถเรียกแบบ property ได้เลยแบบในบรรทัดที่ 11
|
|
เราสามารถสร้าง setter ได้ด้วย @[property_name].setter
ถ้าต้องการสร้าง setter เราจะใช้ชื่อ property แล้วตามด้วย .setter เช่นในตัวอย่างนี้เราต้องการ setter ของ type เราจะใช้ annotation ชื่อ @type.setter ในบรรทัดที่ 6
|
|
ตัวอย่างนี้เราจะทำ input validation แบบง่ายๆ โดยในบรรทัดที่ 8 เราจะเช็คว่า type เป็น Dabbling หรือ Diving รึเปล่า ถ้าไม่ใช้ จะมีการ throw exception ออกมาในบรรทัดที่ 9 ดังนั้นเราจะ set type ได้แค่ Dabbling หรือ Diving เท่านั้น ถ้าใส่อย่างอื่นเข้ามาจะ error
ความสัมพันธ์แบบ Inheritance
การ inherit จะเป็นความสัมพันธ์แบบ Is-a ซึ่งมีความสัมพันธ์ที่ class ลูกจะเป็น(is-a) class แม่ เช่น ในตัวอย่างนี้ เป็นเป็นสัตว์(Duck is-a Animal)
|
|
Association
การสร้างความสัมพันธ์ระหว่าง class จะเป็นความสัมพันธ์แบบ Has_a เช่น ใน Company มี Employee เป็นต้น
เราสามารถระบุความสัมพันธ์ได้ 2 รูปแบบคือ
-
Composition ความสัมพันธ์แบบเป็นส่วนประกอบของ ซึ่งหมายความว่าจำเป็นต้องมี ซึ่งในตัวอย่างนี้เราจะกำหนดให้ Company ต้องมี Employee อย่างน้อย 1 คนถึงจะทำงานได้ ดังนั้นความสัมพันธ์ของ Company และ Employee จะเป็น Composition
จำง่ายๆว่า Composition ใส่ใน Constructor (เป็นตัว C เหมือนกัน)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
class Company: def __init__(self, employee): self.employees = [employee] def displayAllEmployees(self): for employee in self.employees: print(f'{employee._firstname} {employee._lastname}') class Employee: _firstname = "" _lastname = "" def main(): employee1 = Employee() employee1._firstname = 'John' employee1._lastname = 'Doe' company1 = Company(employee1) company1.displayAllEmployees() if __name__ == '__main__': main()
-
Association เป็นความสัมพันธ์แบบที่เบาบางลง(เอาไป reuse ได้ง่ายขึ้น) เราจะสร้าง object ขึ้่นมาแบบต่างคนต่างอยู่และมาทำความรู้จักกันทีหลัง
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
class Company: employees = [] def addEmployee(self, employee): self.employees.append(employee) def displayAllEmployees(self): for employee in self.employees: print(f'{employee._firstname} {employee._lastname}') class Employee: _firstname = "" _lastname = "" def main(): employee1 = Employee() employee1._firstname = 'John' employee1._lastname = 'Doe' company1 = Company() company1.addEmployee(employee1) company1.displayAllEmployees() if __name__ == '__main__': main()
ในตัวอย่างนี้เราจะสร้าง object employee1 และ company1 ในบรรทัดที่ 16 และ 21 ตามลำดับ หลังจากนั้นทั้ง 2 object นี้จะมารู้จักกันด้วย method addEmployee ในบรรทัดที่ 22 ซึ่งในกรณีนี้เป็นความสัมพันธ์แบบ Association(Company สามารถอยุ่ได้โดยที่ไม่มี Employee)