共変性と反変性をグーグルで検索すると、より複雑なタイピングに関する有用な情報が見つかる場合があります。
Javaプログラムで使用できるバイトコードにコンパイルされるScalaを使用してもかまわない場合は、Scala'sを使用すると、この種のことを実行するための優れた構文が提供されます(Java以降)。
クラスフルーツ
クラスバスケット[T<:フルーツ] {
def addToBasket(fruit:T)= {}
}
クラスAppleはFruitを拡張します
クラスレモンはフルーツを拡張します
クラスAppleBasketはBasket[Apple]を拡張します
valapplebasket=新しいAppleBasket
applebasket.addToBasket(新しいApple)
applebasket.addToBasket(新しいレモン)
このコードスニペットの最後の行は、コンパイル時のエラーを示しています。
$ scala Test.scala
C:\ cygwin \ home \ user \ Test.scala:18:エラー:タイプの不一致;
見つかった:this.Lemon
必須:this.Apple
applebasket.addToBasket(新しいレモン)
^
1つのエラーが見つかりました
私は最近Scalaで遊んでいるので、Javaでこれについて考えるのに苦労していますが、Javaではおそらく次のようなことをするでしょう。
クラスFruit{}
クラスAppleはFruit{}を拡張します
クラスLemonはFruit{}を拡張します
クラスBasket<Textends Fruit> {
public void addToBasket(T foo){}
}
クラスBlah{
void doIt(){
Apple a = new Apple();
バスケットb=新しいバスケット<Apple>();
b.addToBasket(a);
レモンl=new Lemon();
b.addToBasket(l);
}
}
b.addToBasket(l)行では、次のコンパイル時タイプのエラーが発生します。
タイプBasket<Apple>のメソッドaddToBasket(Apple)は、引数には適用できません(レモン)
同じコンパイルエラーを発生させる別のオプション(コメントからコピーして明確にする):
// Fruit、Apple、Basketの定義は同じですが、次のようになります。
クラスAppleBasketはBasket<Apple>{}を拡張します
クラスBlah{
void doIt(){
Apple a = new Apple();
バスケット<アップル>b= new AppleBasket();
b.addToBasket(a);
レモンl=new Lemon();
b.addToBasket(l);
}
}