เลือกเมท็อดไหนดี ?


นัท : ถ้า overloaded methods หลายๆ ตัวมี parameters จำนวนเท่ากัน แต่ประเภทต่างกันบ้าง  เวลาเราเรียกใช้แบบส่ง arguments ต่างๆ ซึ่งมีประเภทไม่ตรงกับ parameters ของเมท็อดเหล่านี้แบบเป๊ะๆ แล้วเขาจะเลือก methods ไหนให้  ?

ได้ลองดูบ้างบางกรณีที่แปลผ่าน บางกรณีก็ฟ้องว่ากำกวม  อยากรู้กฎการเลือกเมท็อดที่แน่นอน

1: public class A {

2: public static void main(String[] args) {

3: new A().g(1, 1, 1);

4: }

5: void g(int x, long y, int z) {System.out.println("1");}

6: void g(int x, double y, int z) {System.out.println("2");}

7: }

แบบนี้แปลผ่าน และเลือกเมท็อดแรก

1: public class A {

2: public static void main(String[] args) {

3: new A().g(1, 1, 1);

4: }

5: void g(int x, long y, int z) {System.out.println("1");}

6: void g(long x, int y, int z) {System.out.println("2");}

7: }

แบบบนนี้แปลไม่ผ่าน บ่นว่ากำกวม


พ่อ : เปิดดู Java Language Specification หัวข้อ 15.12.2.2 พบว่ามีใจความท่อนหนึ่งเขียนไว้อย่างนี้

"The Java programming language uses the rule that the most specific method is chosen."

"The informal intuition is that one method declaration is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error."


วิธีการเลือก method ที่จะเรียก จะนำ methods ทั้งหลายที่รับ arguments ต่างๆ ที่ต้องการส่งได้ มาพิจารณาเพื่อเลือกอันที่ specific มากสุด
 

การพิจารณาว่าใคร specific กว่าใครหรือไม่ กระทำดังนี้

ถ้า  parameters ของ method หนึ่งสามารถส่งไปให้ parameters ในอีก method หนึ่งได้หมด ถือได้ว่า method แรก specific มากกว่า method หลัง


ตัวอย่างที่ 1

void g(int x, int y, byte z) {}
void g(int x, long y, int z) {}
void g(long x, int y, long z) {}

ถ้าต้องการเรียก g(1,1,1) จะตัด method แรกออกจากการพิจารณา เพราะรับ byte ที่เหลือสองเมท็อด พบว่าเราไม่สามารถนำ parameters ของ method ที่สองส่งให้ method ที่สาม (ติดตัวกลาง long y ส่งให้ int y ไม่ได้)
และในทางกลับกัน เราก็ไม่สามารถนำ parameters ของ method ที่สามส่งให้ method ที่สอง (ติดตัวแรก และหลัง) แบบนี้การเรียกใช้ g(1,1,1) จะ compile ไม่ผ่าน เพราะ g(1,1,1) ส่งให้ method ที่สองและสามได้ แต่ไม่มีตัวใด specific กว่ากัน


ตัวอย่างที่ 2

void g(int x, long y, int z) {}
void g(int x, double y, int z) {}

ถ้าต้องการเรียก g(1,1,1) พบว่า method ทั้งสองรับได้  พิจารณาทั้งสอง methods นี้ จะพบว่าเราสามารถนำ parameters ของ method แรก ส่งให้ method หลังได้หมด (ตัวแรกและตัวหลังเหมือนกัน ส่วนตัวกลาง long y ส่งให้ double y ได้) แบบนี้การเรียกใช้ g(1,1,1) จะ compile ผ่าน และเลือก method แรก เพราะ specific กว่า


นัท : ขอกลับไปทดลองดูค่ะ


เกร็ดกาแฟ

Copyright 2003 Somchai Prasitjutrakul