Tuesday, January 6, 2015

Java กับ Generic Class

เวลาสร้างคลาสในจาวา เราก็คงอยากให้คลาสของเรารองรับตัวแปรหลายๆประเภท แล้วจะทำได้อย่างไร ทางออกหนึ่งก็คือ Generic Class นี่ล่ะครับ เราสามารถกำหนดให้มันใช้ตัวแปรแบบกลางๆ (ไม่ต้องระบุว่าเป็น int, char, double ฯลฯ)

ลองดูตัวอย่างการสร้างตัวแปรของคลาสที่เป็นแบบ int และการ set กับ get ตามปกติกันก่อน

public class MyClass{
    private int value;
    public void set(int v){
        value = v;
    }
    public int get(){
        return value;
    }
    
    public static void main(String[] args){
        MyClass m = new MyClass();
        m.set(5);
        System.out.println(m.get());
    }
}
แน่นอนครับ ผลลัพธ์ที่ได้ก็คือเลข 5 นั่นเอง

คราวนี้ ถ้าเราต้องการส่งค่าที่ไม่ใช่ตัวเลข เช่น m.set("Hello"); ไป สิ่งที่เกิดขึ้นก็คือ compile ไม่ผ่าน เพราะชนิดของข้อมูลที่ส่งไป กับชนิดของข้อมูลที่เอาไปรับไม่ตรงกัน ก็จำเป็นจะต้องเขียน method ใหม่ แถมยังไม่พอ ต้องประกาศตัวแปรของคลาสใหม่เพื่อมารับข้อมูลชนิดนี้ด้วย

เพื่อที่จะลดความซับซ้อนตรงนี้ลง (แต่ไปเพิ่มความงงให้กับการเขียนโปรแกรม) ลองใช้ Generic class กันดูตามนี้ครับ

public class MyClass<T>{
    private T value;
    public void set(T v){
        value = v;
    }
    public T get(){
        return value;
    }
    
    public static void main(String[] args){
        //MyClass m = new MyClass();
        MyClass<Integer> m1 = new MyClass<Integer>();        
        //m.set(10);
        m1.set(new Integer(10));
        System.out.println(m1.get());
        
        MyClass<String> m2 = new MyClass<String>();
        m2.set(new String("Hello"));
        System.out.println(m2.get());
    }
}

ผลลัพธ์ที่ได้คือ
10
Hello

ซึ่งจะสังเกตเห็นว่า เราก็ยังมีคลาสเดียว แต่ตอนสร้าง Object เราสร้างมันสองตัวคือ m1 เป็นแบบ Integer และ m2 เป็นแบบ String แต่ทั้งสอง Object ก็ใช้ตัวแปรคลาสและ method ร่วมกันได้

ข้อสังเกต

  1. เราสร้างคลาสด้วย public class MyClass<T> ซึ่งหลังคลาสจะตามด้วย Generic type ที่ระบุด้วยเครื่องหมาย <T> และตัว T ก็เป็นชื่อชนิด (จะตั้งเป็นตัวอื่นก็ได้ แต่มักใช้ T แทน Type)
  2. จากนั้นเราก็ใช้ T เหมือนชนิดของตัวแปรทั่วไป เช่น private T valueก็คือการกำหนดให้ตัวแปร value เป็นชนิด T ซึ่งจะกลายเป็น reference type เช่น Integer, Double, String ในอนาคตได้
  3. ในส่วนของ main() เวลาสร้าง Object ต้องระบุชนิดตามหลังคลาสด้วย (สังเกตว่าสัญลักษณ์ ตามติดหลังชื่อคลาสตลอด) เช่น MyClass<Integer> m1 = new MyClass<Integer>(); ซึ่งในจาวารุ่น 7.0 ไป เราสามารถลดรูปให้เหลือแค่ MyClass<Integer> m1 = new MyClass<>(); ได้
  4. เวลาส่งค่าให้ method ของ Generic class ในกรณีนี้ เราก็ไม่สามารถส่งค่าตัวแปรแบบทั่วไปได้ ต้องส่งเป็น Object ของคลาสไป เช่น m1.set(new Integer(10)); แทน

No comments:

Post a Comment