多重ディスパッチ
多重ディスパッチの話を読んで例を作ってみた。
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);
}
}
|