Overriding trong Java là single dispatch

Không có gì đặc biệt, nhưng có lẽ cũng phải ghi lại.

Trước hết, cho hai class Animal và Cat:

class Animal {} 
class Cat extends Animal {}

Tiếp theo cho class Hunter và BetterHunter:

class Hunter { 
    public void Kill(Animal a) { System.out.println("Hunter killed Animal"); } 
    public void Kill(Cat c) { System.out.println("Hunter killed Cat"); } 
} 
class BetterHunter extends Hunter { 
    public void Kill(Animal a) { System.out.println("BetterHunter killed Animal"); } 
    public void Kill(Cat c) { System.out.println("BetterHunter killed Cat"); } 
}

Bây giờ xét tình huống sau, kết quả in ra là gì?

Animal a = new Cat(); 
Hunter h = new BetterHunter(); 
h.Kill(a);

Vì h trỏ đến BetterHunter, JVM phân giải h.Kill thành Kill của BetterHunter. Sau đó, vì a trỏ đến Cat, JVM chọn Kill(Cat). Kết quả là “BetterHunter killed Cat”.

Sai. Java chỉ hỗ trợ Single dispatch, vì overriding được hiện thực nhờ vtable. Nói cách khác JVM chỉ phân giải method dựa vào tham số đầu tiên (this). Bước thứ hai (chọn Kill nào) được thực hiện trong lúc biên dịch (overload). Vì vậy Kill của BetterHunter vẫn được gọi, nhưng là Kill(Animal). Kết quả là “BetterHunter killed Animal”.

Để có Double dispatch, tức là gọi Kill(Cat), xem Thinking in Java, hoặc pattern Visitor.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s