/ 365วันแห่งโปรแกรม

[365 วันแห่งโปรแกรม #day38] Generic Programming

วันที่สามสิบแปดของ ‪#‎365วันแห่งโปรแกรม วันนี้ขอนำเสนอเรื่อง Generic Programming


อย่างที่เราได้คุยกันมาในวันแรกๆ Generic เป็นรูปแบบหนึ่งของการทำ Polymorphism คำจำกัดความของ Generic Programming ที่ง่ายๆ ก็น่าจะประมาณ การเขียนโปรแกรมโดยที่ยังไม่ระบุ type ของ return หรือพารามิเตอร์ (to-be-specified-later) ปกติแล้วเวลาเราเขียนฟังกชันหรือเมธอด เราก็จะระบุไปเลยว่ามี return type แบบนี้นะ รับพารามิเตอร์เป็น type นี้นะ แต่ด้วยความสามารถของ Generic ทำให้เราสามารถทิ้งไว้ก่อน แล้วเดี๋ยวค่อยระบุ type ตอนเอาไปใช้งานได้

ทำไมต้องใช้ Generic

อย่างที่เรารู้กันว่าในหลายๆ ครั้งเราต้องเขียนคลาสหรือฟังก์ชันที่มีหน้าตาเหมือนกันเลย การทำงานแบบเดียวกันเลย แต่มี return type หรือ type ของพารามิเตอร์ต่างกัน นั่นทำให้เราต้องเขียโค้ดที่ซ้ำซ้อน และทำให้การบริหารจัดการยาก

ตัวอย่างที่ง่ายที่สุดของ Generic Programming ก็น่าจะเป็นเรื่อง Collection หรือ Data structure ต่างๆ เช่น List หากเรากำหนดตายตัวว่า List จะสามารถมีสมาชิกเป็น Foo เท่านั้น แล้วถ้าวันนึงในโปรแกรมเราอยากทำ List ของ Bar บ้างล่ะ? ก็ต้องเขียนใหม่ไงครับ แต่ถ้าเราใช้ Generic Programming เข้ามาช่วย เราสามารถเขียน List ตวเดียว แล้วเวลาเอาไปใช้ค่อยระบุว่าใช้กับ Object ของคลาสไหนแค่นั้นเลย

มีคำอื่นที่หมายถึง Generic เหมือนกันไหม

ในภาษาโปรแกรมส่วนใหญ่ใช้คำว่า Generic เลยครับ เช่นใน Java, C#, VB, Ada เป็นต้น แต่ก็มีภาษาเชิงฟังก์ชน เช่น Haskell, ML, Scala ที่เรียกว่า parametric polymorphism หรือในภาษาอย่าง C++ หรือ D ก็เรียกแทน Generic ว่า Template

หน้าตาของสิ่งที่เขียนด้วย Generic programming เป็นอย่างไร

ส่วนใหญ่แล้วเรามักจะพบ Generic คู่กับพวก Collection / Data Structure ต่างๆ นั่นแหละครับ และในแทบทุกภาษาที่รองรับ Generic ก็จะใช้ แทน type parameter

ตัวอย่างของ List แบบ Generic ในภาษา Java

List<Foo> foos = new ArrayList<Foo>();

จากโค้ดข้างต้นจะเห็นว่ามี อยู่หลัง List (ซื่งเป็นชื่อ type) เจ้าเครื่องหมายนี้ใช้บอกว่าต่อไปใน object ที่จะสร้างนี้ ให้แทน type ที่ไม่ถูกระบุไว้ด้วย Foo นั่นเอง แล้วพอเราเอาไปใช้เราก็สั่งได้เหมือนว่า List นี้สร้างมาเพื่อ Foo เองเลย

foos.add(new Foo());
Foo foo = foos.get(0);

เห็นไหมครับ เราสามารถ add foo ลงใน List ได้โดยตรงเลย แล้วก็ยังดึงข้อมูลออกมาใส่ตัวแปรชนิด Foo ได้อีกด้วย

ถ้าเราไม่ระบุล่ะว่า List นี้เป็นของ Foo จะเกิดอะไรขึ้น? ในบางภาษายอมให้คอมไพล์ได้เหมือนกันถ้าไม่ระบุ type parameter โดยมันจะถือว่าเราระบุ type เป็น type ที่อยู่สูงที่สุดในระบบ เช่นใน Java ก็คือ Object มาดูตัวอย่างกันดีกว่าครับ

List foos = new ArrayList();
foos.add(new Foo());
Foo foo = (Foo) foos.get(0);

จะเห็นว่าก็ใช้ได้เหมือนกัน เราสามารถใส่ object ของ Foo ลงใน List ได้เหมือนเดิมเลย แต่ตอนที่ get ขึ้นมาต้องทำ down casting ครับ เนื่องจากว่า List นี้เป็น List ของ Object ไม่ใช่ Foo ดังนั้นถ้าเราจะ pass ใส่ Foo ก็ต้อง cast เองครับ

‎day38 #365วันแห่งโปรแกรม ‪#‎โครงการ365วันแห่ง‬...