What is polymorphism?
นึกย้อนกลับไปเมื่อประมาณวันอังคารที่แล้ว ในการสอบสัมภาษณ์ committee ถามว่า “polymophism คืออะไร?” กับเด็กจบใหม่ที่มาสมัครงานคนหนึ่ง (คำถามคลาสสิค) – คำตอบที่ได้กลับมาคือ
“มันคือ method overloading ครับ/ค่ะ”
ใช่ครับ อาจารย์พี่ก็สอนมาแบบนี้…
ผมว่าคำถามนี้มันกึ่งๆ open-ended question คือคำตอบมันขึ้นกับความเข้าใจที่มีใน OO บวกประสบการณ์การเขียนจริง – มันคงไม่ถึงกับผิด ถ้าคุณ ไม่ตอบออกทะเล ที่สำคัญคือคุณตอบ “ครบ” แค่ไหน?
Polymorphism is all around
Method Overloading เป็นส่วนหนึ่งของคอนเซ็ปต์ polymorphism แต่มันไม่ใช่ทั้งหมดของ polymorphism อันนี้ต้องพูดให้เคลียร์นิดนึง – ตามความเข้าใจของผม Polymorphism มีหลายประเภทด้วยกัน
- ad-hoc polymorphism: คือการใช้ inheritance + method overloading + dynamic binding โดยให้ compiler/interpreter เป็นผู้เลือกว่าจะ เรียกการกระทำจาก object ไหนตอนรันไทมน์
- parametic polymorphism: คือการกำหนดประเภทของ object ที่รับ/ส่งเมสเสจแบบ “กว้างๆ” เพื่อให้สามารถใช้ได้กับทุกคลาส (หรือบางคลาส เมื่อมี constraint) ยกตัวอย่างเช่น generic collection – List<T>
พูดง่ายๆคือการรับ/ส่งเมสเสจแบบ “กว้างๆ” ไม่เจาะจงว่าผู้รับ/ส่งจะเป็นใครในขณะที่เขียนโค้ด เดี๋ยวมันก็รู้เองตอนรันนั่นแหละ
So what?
แล้วมันช่วยห่า(น) อะไรกับชีวิตโปรแกรมเมอร์ตาดำๆครับ?
ลองมาดูโค้ดกัน
Rev.1
public void DoSthWithAnimal(Animal animal) {
if(animal is Duck) {
// Do something with a duck
...
} else if(animal is Rat) {
// Do something with a rat
...
} else if(animal is Cat) {
// Do something with a cat
...
}
...
}
ข้อสังเกต:
- Code Readability ต่ำ ลองนึกภาพข้างในแต่ละ if statement มีโค้ดสักร้อยบรรทัด
- จะเปลี่ยนจาก if…else เป็น switch statement ก็ไม่ต่างกันเท่าไหร่
- เมื่อมี conditional statements จากการเช็ค flag อะไรบางอย่าง ความน่าจะเป็นที่จะมีการเช็คแบบเดียวกันซ้ำๆ ในตำแหน่งที่ต่างกันนั้นมีสูง (ต้องเขียนซ้ำๆ copy-paste นั่นแหละ)
Rev. 2
public void DoSthWithAnimal(Animal animal) {
// Do something with a duck, rat, cat or other defined types in the future
animal.Action();
...
}
ข้อสังเกต:
- โค้ดสะอาดขึ้น เพราะย้ายการกระทำที่เป็น common ไปไว้เมทอด Action – หากมีการกระทำไหนที่ Duck, Rat, Cat ต้องการเป็นพิเศษก็ใช้ overloading นิยามเพิ่มเข้าไป
- ทุกจุดที่เคยเช็ค condition ซ้ำๆก็จะหายไป (เลิกนิสัย copy-paste)
- สิ่งสำคัญคือ Maintainability ที่เพิ่มขึ้น เมื่อเกิดความต้องการเช็คประเภทใหม่ในระบบ ไม่จำเป็นต้องเปลี่ยน client code สิ่งที่ต้องทำคือ derive คลาส Animal และ overload method Action ถ้าจำเป็น
Why asking OOP concept during interview?
หลายคนอาจสงสัยว่าทำไมตอนสอบสัมภาษณ์งาน มักเจอคำถามคอนเซ็ปต์ของ OOP? ตอนแรกผมก็ไม่เข้าใจว่าทำไมถึงให้ความสำคัญกับทฤษฎี ในเมื่อเขียนโค้ดได้ก็น่าจะพอ – แต่พอทำงานไปสักสาม-สี่ปีก็ถึงบางอ้อ
เพราะ scale ของงานมันต่างกับตอนเรียน โปรเจ็กต์ขนาดกลางถึงใหญ่ที่มีโค้ดหลายพัน-หมื่นบรรทัดนั้น การเขียนให้ maintainable ไม่ใช่เรื่องง่ายเลยจริงๆ
หากว่าสักแต่เขียน เมื่อมี requirement ใหม่เข้ามา อาจถึงกับต้องทำการ “รื้อ” เลยทีเดียว – บ่อยครั้งที่การเพิ่มฟีเจอร์ง่ายๆกลับกลายเป็นเรื่องยาก เพราะคนเขียนไม่ให้ความสำคัญกับทฤษฎีตั้งแต่แรก
ส่งท้ายด้วย quote ของเจ้าพ่อ Martin Fowler:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand. – Martin Fowler
Summary
- ตัวอย่างที่กล่าวมาข้างต้นเป็นวิธีใช้ polymophism อย่างหนึ่งของการ refactoring ดูรายละเอียดได้ที่ refactoring.com หรือหนังสือของ Martin Fowler
- ที่จริงยังมีนิยามประเภทของ polymorphism อีกสองอย่างคือ coercion และ inclusion แต่ไม่พูดถึงในที่นี้ ดูรายละเอียดได้ที่ Java World
- บทความนี้เขียนตามความเข้าใจของผู้เขียน หากผิดพลาดประการใดหรือมีข้อเสนอแนะ ยินดีรับคอมเม้นต์ด้านล่าง
References
4 Comments
ท่าทางจะโมโห
อย่ากระโดดกััดคอเด็กล่ะ
มิน่าล่ะ โดนเคี่ยวเข็ญเรื่อง OOP ทู้กที
ประสบการณ์ตรงเลยนะเนี่ย
คำเค้าคมจริงๆ