The HIRO Says

If you smell what The HIRO is cooking!!!

【Generics】型パラメータの拡張(2)−super

型パラメータには、<? super E>という書き方もあります。
今回は、この super について説明します。

前回使用した Stack クラスに、popAll() メソッドを定義するとします。
popAll() メソッドは、Stack の要素を全て、引数の Collection に add するという内容とします。
(引数にデータを移すことがポイント)

    public void popAll(Collection dst) {
        while (!this.isEmpty()) {
            dst.add(this.pop());
        }
    }

問題点

前回と同じで、型パラメータが一致しないとコンパイルエラーになります。

    Stack target = new Stack();
    target.popAll(new ArrayList());

【エラーメッセージ】
popAll(Collection) は 引数 (List) に適用できません。

解決策

前回は、引数の値を Stack 内で使用しました。
今回は、Stack の値を引数にセットします。
つまり、データの流れが前回と逆になります。


このような場合は、super を使います。

    public void popAll(Collection<? super E> dst) {

指針

今回の popAll のように、型パラメータがクラス定義と一致しない場合かつ、プログラム内の値を引数にセットする処理を行う場合、super と定義するとうまく行きます。
面倒くさいですね。

PECS

Effective Java(原著)によると、この extends と super のルールは、”PECS”として覚えると良いそうです。
PECS:「Producer-Extends, Consumer-Super」の略

  1. producer:引数がプログラム内で使用されるものの場合(引数から内部データを「生成する」という意味か)
  2. consumer:引数がプログラムからセットされるものの場合(引数が内部データを「消費する」という意味か)