多重ディスパッチ

多重ディスパッチの話を読んで例を作ってみた。
http://d.hatena.ne.jp/hayamiz/20080303/1204567501

Javaではx.method(y, z,...)のxだけが特別扱いで、xの実行時の型によってどのメソッドが呼ばれるかを決める。しかしyやzなどの引数の実行時の型はメソッドを選ぶ際には使われない。コンパイル時に宣言されている型をつかってメソッドが選ばれる。

下のコードはa.sayというメソッドの呼び出しは実行時にaの型によってCat#sayやDog#sayが選ばれる。しかしz.enter(a)と引数として渡した場合にはZoo#enter(Cat)とZoo#enter(Dog)から選んではくれない。Zoo#enter(Animal)が無いぞ、とエラーになる。

import java.util.ArrayList;

public class TestMultiDispatch {
    public static void main(String[] args) {
        Zoo z = new Zoo();
        for(Animal a: new Animal[]{new Cat(), new Dog(), new Cat()}){
            //z.enter(a); // コンパイルエラー
            a.say();
        }
    }
}
class Zoo{
    ArrayList<Dog> dogs = new ArrayList<Dog>();
    ArrayList<Cat> cats = new ArrayList<Cat>();
    public void enter(Cat cat){
        cats.add(cat);
    }
    public void enter(Dog dog){
        dogs.add(dog);
    }
}
abstract class Animal{
    abstract public void say();
}
class Cat extends Animal{
    public void say(){
        System.out.println("にゃ〜");
    }
}
class Dog extends Animal{
    public void say(){
        System.out.println("わん!");
    }    
}

Animalにenterメソッドをつければ一応は解決できる。

>||java|
abstract class Animal{
abstract public void say();
abstract public void enter(Zoo z);
}
class Cat extends Animal{
public void say(){
System.out.println("にゃ〜");
}
public void enter(Zoo z){
z.enter(this);
}
}
class Dog extends Animal{
public void say(){
System.out.println("わん!");
}
public void enter(Zoo z){
z.enter(this);
}
}
|