「こんにちは! エリーのジェネリック医薬品に関するレッスンを続けます。聞く準備はできていますか?」

"はい。"

「それでは始めましょう。」

「まず知っておく必要があるのは、クラスのメソッドも独自の型パラメータを持つことができるということです。」

"知っている。"

「いいえ、特に独自の型パラメータのことを指します。

class Calculator
{
  T add(T a, T b); // Add
  T sub(T a, T b); // Subtract
  T mul(T a, T b); // Multiply
  T div(T a, T b); // Divide
}

「これらの型パラメータはメソッドに特に関係します。クラスにはパラメータがありません。これらのメソッドを静的として宣言し、オブジェクトなしで呼び出すこともできます。」

「なるほど。メソッドの型パラメータのポイントはクラスの場合と同じですか?」

「はい。でも、何か新しいことがあります。」

「すでにご存知のとおり、型宣言ではワイルドカードを使用できます。次に、次の状況を想像してください。」

例1
public void doSomething(List<? extends MyClass> list)
{
 for(MyClass object : list)
 {
  System.out.println(object.getState()); // Everything works well here.
 }
}

「しかし、コレクションに新しいアイテムを追加したい場合はどうすればよいでしょうか。」

例 2
public void doSomething(List<? extends MyClass> list)
{
 list.add(new MyClass()); // Error!
}

「問題は、一般的な場合、doSomething メソッドには、要素が MyClass オブジェクトではなく、MyClass のサブクラスのオブジェクトである List が渡される可能性があることです。しかし、そのようなリストに MyClass オブジェクトを追加することはできません。」

「ああ。それで、どうしたらいいでしょうか?」

「何もありません。この状況では何もできません。しかし、このことが Java の作成者に考えるきっかけを与えました。そして彼らは新しいキーワードを思いつきました。それはsuperです。」

「構文はほとんど同じです:」

List<? super MyClass> list

ただし、extend と super の間には重要な違いがあります。

「«? extends T» は、クラスが T の子孫である必要があることを意味します。」

「«? スーパー T» は、クラスが T の祖先である必要があることを意味します。」

「なんてことだ。それで、これはどこで使われるの?」

「«? super T» は、メソッドに T オブジェクトのコレクションへの追加が含まれる場合に使用されます。この場合、それは T オブジェクトのコレクションまたは T の祖先である可能性があります。」

「ああ。AT オブジェクトは、T の先祖のいずれかの型を持つ参照変数に代入できます。」

「正直に言うと、このアプローチはあまり使用されません。さらに、欠点もあります。たとえば、次のようなものです。」

public void doSomething(List<? super MyClass> list)
{
 for(MyClass object : list) // Error!
 {
  System.out.println(object.getState());
 }
}
public void doSomething(List<? super MyClass> list)
{
 list.add(new MyClass()); // Everything works well here.
}

「最初の例は機能しません。」

「list は List<Object> (Object は MyClass の最上位のスーパークラス) である可能性もあるため、基本的に次の無効なコードを記述していることになります。」

例1
List<Object> list; 

for(MyClass object : list) // Error!
{ 
 System.out.println(object.getState()); 
}

「なるほど。興味深い授業をありがとう。」

"どういたしまして。"