Javaジェネリクス入門、その5

Javaジェネリクス入門、その4の続きである。

前回はジェネリックメソッドについて説明したが、以前に戻ってジェネリッククラスをもう少し追求してみることにする。

複数の型パラメータ

これまではジェネリッククラスに一つの型パラメータのある場合を考えてきたが、型パラメータはいくつでもよい。もちろん、3つ以上というのは、私自身も書いたことが無いし、見たことがたぶん無いと思うのだが、とりあえず二つの場合である。

以下のような例を考えてみる。

public class Sample {  

  /** 生物階層 */
  static class Creature {
  }
  static class Fish extends Creature {    
  }
  static class Dog extends Creature {    
  }
  static class Human extends Creature {    
  }

  /** 食べ物階層 */
  public static class Food {    
  }
  public static class Plankton extends Food {    
  }
  public static class DogFood extends Food {    
  }
  public static class Rice extends Food {    
  }

  /** 動物園。何らかの生き物とその食べ物 */  
  public static class Zoo<C extends Creature, F extends Food> {
  }
}

ここでは、生物のクラス階層があり、食べ物のクラス階層があり、それらを組み合わせた動物園がある。この動物園は例えば次のように使う。

  // こういう使い方もできるし、
  static Zoo<Human, Rice>humanZoo = new Zoo<>();

  // こういう使い方もできる
  public static class HumanZoo extends Zoo<Human, Rice> {
  }

第一型パラメータとしては生物でなくてはならないので、ここではHumanを指定してみた。第二型パラメータとしてはRiceである。

単純に型パラメータの数を増やしただけであることがわかると思う。さらに、一部の型パラメータのみを指定して、新たなクラスを作成することもできる。

  public static class DogFoodZoo<C extends Creature> extends Zoo<C, DogFood> {
  }

このクラスでは、生物は何でも指定できるのだが、食べ物はドッグフードに限られており変更することはできない。
可哀想なのだが、人間を集めてドッグフードのみを食わせる動物園は以下になる。

  static DogFoodZoo<Human> dogFoodHumanZoo = new DogFoodZoo<>();

このように、型パラメータはいくつでも使用することができるし、その一部の型パラメータを固定してしまい、数を減らすこともできる。以前書いたように、より限定することも可能だ。

  public static class DogFood extends Food {    
  }
  public static class ADogFood extends DogFood {
  }
  public static class ADogFood1 extends ADogFood { 
  }
  public static class BDogFood extends DogFood {
  }

などと、ドッグフードにもいろいろ種類があるとし、今A社のドッグフードでなければダメという場合は、

  public static class ADogFoodZoo<C extends Creature, F extends ADogFood> extends Zoo<C, F> {
  }

のようにして、限定したクラスを作成することができる。もちろん以前に記述したように、「型パラメータを限定したクラスの中では、その限定された型パラメータに特有の機能を使うことができる」。いまA社のドッグフードに限定したので、このクラスの中ではA社のドッグフードに特徴的な機能を使えることになるかもしれない。