汎用インターフェースがあります
public interface Consumer<E> {
public void consume(E e);
}
2 種類のオブジェクトを消費するクラスがあるので、次のようなことをしたいと思います。
public class TwoTypesConsumer implements Consumer<Tomato>, Consumer<Apple>
{
public void consume(Tomato t) { ..... }
public void consume(Apple a) { ...... }
}
どうやらそれはできないようです。
もちろん自分でディスパッチを実装することもできます。例えば
public class TwoTypesConsumer implements Consumer<Object> {
public void consume(Object o) {
if (o instanceof Tomato) { ..... }
else if (o instanceof Apple) { ..... }
else { throw new IllegalArgumentException(...) }
}
}
しかし、私はジェネリックが提供するコンパイル時の型チェックとディスパッチのソリューションを探しています。
私が考えられる最善の解決策は、別々のインターフェースを定義することです。例えば
public interface AppleConsumer {
public void consume(Apple a);
}
機能的には、この解決策は問題ないと思います。ただ冗長で見苦しいだけです。
何か案は?
ベストアンサー1
カプセル化を検討してください:
public class TwoTypesConsumer {
private TomatoConsumer tomatoConsumer = new TomatoConsumer();
private AppleConsumer appleConsumer = new AppleConsumer();
public void consume(Tomato t) {
tomatoConsumer.consume(t);
}
public void consume(Apple a) {
appleConsumer.consume(a);
}
public static class TomatoConsumer implements Consumer<Tomato> {
public void consume(Tomato t) { ..... }
}
public static class AppleConsumer implements Consumer<Apple> {
public void consume(Apple a) { ..... }
}
}
これらの静的内部クラスの作成が面倒な場合は、匿名クラスを使用できます。
public class TwoTypesConsumer {
private Consumer<Tomato> tomatoConsumer = new Consumer<Tomato>() {
public void consume(Tomato t) {
}
};
private Consumer<Apple> appleConsumer = new Consumer<Apple>() {
public void consume(Apple a) {
}
};
public void consume(Tomato t) {
tomatoConsumer.consume(t);
}
public void consume(Apple a) {
appleConsumer.consume(a);
}
}