Javaの "? extends" や "? super" の使い方をC#やScala風に考える

いきなりですが、次のコードの良くないところはどこでしょう？

```java
interface Foo {
	Comparator<Integer> getComparator();
}
```

なお `Comparator` は `java.util` パッケージに含まれるインタフェースで次のように宣言されています。

```java
interface Comparator<T> {
	int compare(T o1, T o2);
}
```

__答え__

`Foo` をより良く書きなおすと次のようになります。

```java
interface Foo {
	Comparator<? super Integer> getComparator();
}
```

`? super` や `? extends` （下限または上限つきワイルドカード）は Java でジェネリクスを使う上で特に難しい部分です。比較的新しい言語（ C# 、 Scala 、 Ceylon など）では同じ目的のためによりシンプルでわかりやすいアプローチがとられています。

Java が採用した方法は __Use-site variance annotation__ と呼ばれ、 C# などが採用した方法は __Declaration-site variance annotation__ と呼ばれます。本投稿では __Declaration-site variance annotation の考え方をベースに Java でどのように `? extends` や `? super` を使えば良いか__ について書きます。

これは必ずしも Java で一般的な方法ではありません。 Java の `? super` や `? extends` の使い方については _PECS_ が有名ですが、一部それと異なる結果になります。　 _PECS_ との違いも最後に述べます。

想定読者
--------------------------------------------------------------

### 前提知識

- Java のコードが読める
- 継承とポリモーフィズムについて理解している
- ジェネリクスの基本について理解している（ `List<String>` が意味することはわかる）

### 読むといいと思う人

- `? super` や `? extends` って何？という人
- `? super` や `? extends` をなんとなく使ったことはあるけどよくわかっていない人
- 基本的な使い方はわかっているけど、ジェネリック型が入れ子になるなど複雑なケースでよくわからない人
- Java しか知らず、他の言語での考え方について学びたい人
- _Variance（変性）_ って何？という人
- _Variance_ について聞いたことはあるけどよくわかっていない人
- _PECS_ って何？という人（比較するために _PECS_ についても簡単に説明しています）

本投稿での表記について
--------------------------------------------------------------

### コードのタイトル部

本投稿では _Declaration-site variance annotation_ と _Use-site variance annotation_ の両方を扱うため、文中のコードがどちらを意図しているかわかりやすいように、タイトル部に Declaration-site または Use-site と表記しています。

```java:Declaration-site
// Declaration-site variance annotation のコード
```

```java:Use-site
// Use-site variance annotation のコード
```

何の表記もない場合は両者に共通のコードです。

_Declaration-site variance annotation_ のコードは Java プログラマが理解しやすいように Java 風に書いていますが、 Java ではコンパイルできません。

### Annotation

本投稿で _Annotation_ と言った場合には、 _Declaration-site variance annotation_ で使われる `in` と `out` 、 _Use-site variance annotation_ で使われる `? super` と `? extends` などのことを指します。Javaのアノテーション（ `@Override` など）のことではないので注意して下さい。 Java のアノテーションについてはカタカナで「アノテーション」と書きます。

### ※（補足）

本文中に次のような形で補足を挿入しています。

_<span style="font-size: smaller;">※ これは補足の例です。</span>_

特に、厳密な説明をすることで話がわかりづらくなる箇所についてあえてやや不正確な説明をした上で、補足でより正確な説明をしている箇所があります。

Hello, Variance!!
--------------------------------------------------------------

まずは __Variance（変性）__ の例について見てみましょう。

`Animal` クラスを継承した `Cat` クラスがあるとします。そこで、次のようなコードを考えてみます。

```java
List<Cat> cats = new ArrayList<>();
List<Animal> animals = cats; // List<Cat>をList<Animal>に代入
animals.forEach(System.out::println); // animalsの要素を表示（ Java 8 の構文を使用）
```

一見、 `Cat` は `Animal` の派生型なので `List<Cat>` を `List<Animal>` に代入しても問題ないように思えます。しかし、このコードはコンパイルエラーになります。

いったい何が問題なのでしょう？次のコードを見ればその理由が分かります。

```java
List<Cat> cats = new ArrayList<>();
List<Animal> animals = cats;
animals.add(new Animal()); // 実体はList<Cat>なのにAnimalを追加！？
```

上記コードのように、もし `cats` が `animals` に代入できるなら `List<Cat>` に `Animal` を追加するコードが書けることになり、コンパイル時の型チェックをすり抜けて実行時エラーになってしまいます。

とは言え、 `List` に変更を加えなければ問題ないのに、 `List<Cat>` と `List<Animal>` に一切互換性がないも不便です。次のように書けば `cats` を `animals` に代入できます。

```java
List<Cat> cats = new ArrayList<>();
List<? extends Animal> animals = cats;
animals.forEach(System.out::println);
```

Java では `? extends` をつけることによって _Variance_ を変更することができ、型パラメータの異なる `List` に互換性を持たせることができます。

次に _Variance_ について詳しく説明します。

継承とVariance
--------------------------------------------------------------

ジェネリクスと _Variance_ について考える準備として、まずは継承と _Variance_ について説明します。

### メソッドの戻り値

次のようなクラス `A` があるとします。

```java
class A {
	Animal makeAnimal() { ... }
}
```

`A` を継承して `makeAnimal` メソッドをオーバーライドします。このとき、 `makeAnimal` の戻り値の型を `Animal` よりも狭い（より特化した） `Cat` に変更することができます。

```java
class B extends A {
	@Override
	Cat makeAnimal() { ... }
}
```

これが許されるのは `Animal` 型の変数に `Cat` を代入できるのと同じ理由によります（ `Cat` は `Animal` を継承しているので `Animal` として振る舞える、 __is-a 関係__ 、 `Cat` is an `Animal` ）。

`Animal` と `Cat` 、 `A` と `B` の間にはそれぞれ継承による派生関係が成り立ちます。派生型と基本型の関係を `派生型` < `基本型` のように書くと、次のように書けます。

- `Cat` < `Animal`
- `B` < `A`

メソッドの戻り値の型（ `Cat` と `Animal` ）とその持ち主の型（ `B` と `A` ）について、派生の方向が一致（両方とも < ）しています。このような状態を __Covariant（共変）__ と呼びます。

上記のように、 __継承におけるメソッドの戻り値の型については Covariant__ になります。

### メソッドの引数

次はメソッドの引数について考えてみます。

```java
class C {
	void useAnimal(Animal animal) { ... }
}
```

`C` を継承して `useAnimal` メソッドをオーバーライドします。同じように引数の型を狭めて `Cat` にするとどうなるでしょうか。

```java
class D extends C {
	@Override
	void useAnimal(Cat cat) { ... }
}
```

これはコンパイルエラーになります。 `D` は `C` を継承しており `C` として振る舞う必要があります。そのためには、 `useAnimal` が引数として `Animal` を受け取れなければなりません。しかし、 `D` の `useAnimal` は `Animal` よりも狭い `Cat` しか受け取れません。よって、 `D` は `C` として振る舞うことができず、 _is-a 関係_ を満たすことができないのでエラーとなります。

逆に、引数の型を広めるとどうなるでしょうか。

```java
class C {
	void useCat(Cat cat) { ... }
}

class D extends C {
	@Override
	void useCat(Animal animal) { ... }
}
```

`D` の `useCat` はより `C` の `useCat` よりも広い型（ `Animal` ）に対応しています。これなら、 `D` が `C` として振る舞うことができそうです。

`Animal` と `Cat` 、 `C` と `D` の関係を不等号で表すと次のようになります。

- `Cat` < `Animal`
- `C` > `D`

引数の時とは異なり、不等号の向きが逆転（ < と > ）しました。このような状態を __Contravariant（反変）__ と呼びます。

一般的に、 __継承におけるメソッドの引数については Contravariant__ となります。

実際には Java の型システムでは、オーバーライドするときにメソッド引数の型を変えることはできません（上記の `useCat` のコードはエラーになります）。不等号（と等号）で表すと

- `Cat` = `Cat` （ここの型を変えることができない）
- `C` > `D`

でなければなりません。そのような関係を __Invariant（非変）__ と呼びます。一般的な型システムについて考えると継承時のメソッドの引数については _Contravariant_ で安全なのですが、 Java の型システムでは _Invariant_ となります。

_<span style="font-size: smaller;">※ Java の型システムではオーバーライドしてメソッドの引数の型を変えた場合は、オーバーライドではなくオーバーロードされた別のメソッドとして扱われます。そのため、 `useCat` のコードから `@Override` を取り除くとエラーでなくなります。引数の型を狭めた場合（ `useAnimal` のコード）でも `@Override` をつけなければオーバーロードとなりエラーになりません。</span>_

_Covariant_ か _Contravariant_ か _Invariant_ かという性質のことを __Variance__ と呼びます。

ジェネリクスとVariance
--------------------------------------------------------------

派生型を作るのは継承だけではありません。ジェネリクスも派生型を作る場合があります。本題に戻ってジェネリクスと _Variance_ について考えてみましょう。

### メソッドの戻り値

最もシンプルな例として、 `T` 型のオブジェクトを返す（供給する）だけの型 `Supplier` （供給者）を考えます。

_<span style="font-size: smaller;">※ `Supplier` は Java 8 で頻出のインタフェースです。</span>_

```java
interface Supplier<T> {
	T get();
}
```

このとき、 `Supplier<Cat>` と `Supplier<Animal>` の関係について考えてみましょう。 `Supplier<Cat>` は `Cat` を供給します。供給された `Cat` は `Animal` として振る舞うことができるので、 `Supplier<Cat>` は `Animal` を供給しているとも考えられます。そのため、 `Supplier<Cat>` は `Supplier<Animal>` として振る舞うことができ、 `Supplier<Cat>` は `Supplier<Animal>` の派生型であると言うことができそうです。

この関係を < を使って書くと次のようになります。

- `Cat` < `Animal`
- `Supplier<Cat>` < `Supplier<Animal>`

不等号の向きがそろっているので、これは継承のときに見たのと同じ _Covariant_ な関係です。

一般的に、 __ジェネリックな型はメソッドの戻り値としてしか使われない型パラメータについて Covariant__ になります。

_<span style="font-size: smaller;">※ 実際には、上記のように宣言するだけでは Covariant として取り扱えません。後述の構文で明示的に Covariant であることを指定する必要があります。</span>_

### メソッドの引数

同じく最もシンプルな例として、 `T` 型のオブジェクトを受け取る（消費する）だけの型 `Consumer` （消費者）を考えます。

_<span style="font-size: smaller;">※ `Consumer` も Java 8 で頻出のインタフェースです。</span>_

```java
interface Consumer<T> {
	void accept(T t);
}
```

このとき、 `Consumer<Cat>` と `Consumer<Animal>` について考えてみましょう。 `Consumer<Cat>` は `Cat` を受け取って消費します。 `Consumer<Animal>` はより広い型 `Animal` を受け取ることができます。 `Consumer<Animal>` は `Consumer<Cat>` として振る舞って `Cat` を受け取ることができるため、 `Consumer<Animal>` は `Consumer<Cat>` の派生型と考えることができそうです。

逆はダメです。 `Consumer<Cat>` が `Consumer<Animal>` として振る舞おうとしても、 `Consumer<Cat>` は `Animal` を受け取れません。

つまり、次のような関係になります。

- `Cat` < `Animal`
- `Consumer<Cat>` > `Consumer<Animal>`

不等号の向きが反転しているので、これは継承の時に見たのと同じ _Contravariant_ な関係です。

一般的に、 __ジェネリックな型はメソッドの引数としてしか使われない型パラメータについて Contravariant__ になります。

_<span style="font-size: smaller;">※ 実際には、上記のように宣言するだけでは Contravariant として取り扱えません。後述の構文で明示的に Contravariant であることを指定する必要があります。</span>_

### Declaration-site variance annotation

_Declaration-site variance annotation_ を採用した言語では、ジェネリクスの型パラメータの宣言（Declaration）に _Annotation_ を付与して Variance を指定することができます。

ここでは C# や Ceylon にならって、 `out` を付けたら _Covariant_ 、 `in` を付けたら _Contravariant_ 、何も付与しなければ _Invariant_ になるとします。 _Covariant_ であるために `out` が付与された型は戻り値でしか使えません。同様に、 _Contravariant_ であるために `in` が付与された型は引数でしか使えません。これに違反するとコンパイルエラーになります。

```java:Declaration-site
interface Supplier<out T> { // outが付与された型は戻り値にしか使えない
	T get();
}

interface Consumer<in T> { // inが付与された型は引数にしか使えない
	void accept(T t);
}
```

このとき、 `Supplier` は Covariant、 `Consumer` は Contravariant なので、次のような代入が可能になります。

```java:Declaration-site
Supplier<Cat> catSupplier = ...;
Supplier<Animal> animalAupplier = catSupplier; // Covariant なので Supplier<Cat> < Supplier<Animal>

Consumer<Animal> animalConsumer = ...;
Consumer<Cat> catConsumer = animalConsumer; // Contravariant なので Consumer<Animal> < Consumer<Cat>
```

また、複数の型パラメータを持つジェネリックな型では、片方について _Covariant_ で、もう一方について _Contravariant_ なケースも考えられます。

最もシンプルな例として、 `T` を受け取り `R` を返すだけの型 `Function` について考えます。 `Function` に `in` 、 `out` を付与すると次のようになります。

_<span style="font-size: smaller;">※ `Function` も Java 8 で頻出のインタフェースです。</span>_

```java:Declaration-site
interface Function<in T, out R> { // T は引数に、 R は戻り値にしか使えない
	R apply(T t);
}
```

`Function` は `T` については Contravariant に、 `R` については Covariant になるので、次のような代入が可能です。

```java:Declaration-site
Function<Animal, Cat> animalToCat = ...;
Function<Cat, Animal> catToAnimal = animalToCat; // TについてはContravariant、RについてはCovariant
```

#### `in`, `out` と引数・戻り値の型のより正確な関係

これまでは意図的に簡略化して次のように説明してきました。

- `out` で型パラメータを宣言 → メソッドの戻り値でのみ利用可
- `in` で型パラメータを宣言 → メソッドの引数でのみ利用可

しかし、これは正確な説明ではありません。次の話に進む前に、型パラメータと引数・戻り値の型のより正確な関係について説明します。

例えば次のコードでは、一見 `out` を付与された `T` が引数で使われているようですが問題ありません。

```java:Declaration-site
interface Foo<out T> {
	void foo(Consumer<T> consumer); // Tが引数で使われているように見えるが問題なし
}
```

`Foo<Cat>` と `Foo<Animal>` について考えてみましょう。 `Consumer` は前の例のように　`Consumer<in T>` なので `T` について _Contravariant_ です。そのため、次のような関係になります。

- `Cat` < `Animal`
- `Consumer<Cat>` > `Consumer<Animal>`

`Consumer<Cat>` > `Consumer<Animal>` ということは、 `Foo<Cat>` の `void foo(Consumer<Cat>)` は `Foo<Animal>` の `void foo(Consumer<Animal>)` よりも広い型に対応できるので

- `Foo<Cat>` < `Foo<Animal>`

となります。 `Foo<Cat>` と `Foo<Animal>` 、 `Cat` と `Animal` で不等号と向きが同じであるため `Foo` は `T` について _Covariant_ であることがわかります。よって、 `Foo` の `T` は `out` に違反していないわけです。

このように、 `out` が付与された型パラメータなら戻り値、 `in` なら引数という単純なルールではなく、その型パラメータについて _Covariant_ 、 _Contravariant_ として扱っても安全かどうかによって `out` 、 `in` に違反していないかが判定されます。

定式化された判定方法は[参考文献1](http://blogs.msdn.com/b/ericlippert/archive/2009/12/03/exact-rules-for-variance-validity.aspx)が詳しいです。

### Use-site variance annotation

_Use-site variance annotation_ を採用した言語では、宣言時ではなく利用（Use）時に付与する _Annotation_ によってジェネリック型の _Variance_ を決定します。

Java では上限・下限付きワイルドカードを _Annotation_ として使い、 `Supplier<? extends Animal>` とすれば _Covariant_ に、 `Supplier<? super Animal>` とすれば _Contravariant_ になります。また、単に `Supplier<Animal>` とすれば _Invariant_ になります。

_Declaration-site variance annotation_ で例に上げた `Supplier` 、 `Consumer` 、 `Function` のコードを _Use-site variance annotation_ で書きなおすと次のようになります。

```java:Use-site
Supplier<Cat> catSupplier = ...;
Supplier<? extends Animal> animalAupplier = catSupplier; // Covariant

Consumer<Animal> animalConsumer = ...;
Consumer<? super Cat> catConsumer = animalConsumer; // Contravariant

Function<Animal, Cat> animalToCat = ...;
Function<? super Cat, ? extends Animal> catToAnimal = animalToCat; // TについてはContravariant、RについてはCovariant
```

#### 欠点

見ての通り、 _Declaration-site variance annotation_ では `Supplier` や `Consumer` などの型を宣言する際に一度だけ `in` や `out` と記述すればいいところが、 _Use-site variance annotation_ ではそれらを利用する際に毎回 `? extends` や `? super` と記述しなければなりません。これは、単に面倒だというだけでなく、 `Supplier` は　_Covariant_ だと想定されているから `? extends` にするといったことを、 __その型の設計者ではなく利用者が常に把握していなければならない__ ことを意味します。

#### 利点

一方で、 _Use-site variance annotation_ では一つの型の _Variance_ を _Invariant_ にも _Covariant_ にも _Contravariant_ にもできるので表現力の幅が広いという利点があります。

例えば、 `Animal` の `List` を受け取って要素を表示するメソッドを考えてみます。

```java
void printAnimals(List<Animal> animals) { ... }
```

このメソッドに `List<Cat>` を渡したくても、 `List` は _Invariant_ なのでこのままでは渡せません。

```java
List<Cat> cats = ...;
printAnimals(cats); // コンパイルエラー（ List<Cat> is NOT a List<Animal> ）
```

`printAnimals` は単に渡された `List` から `Animal` を取り出して表示するだけなので、 `List` には何の変更も加えません。そのため、このメソッドに限っては `List` が _Covantiant_ であると考えても問題はおこりません。そこで、 `? extends` を使って _Variance_ を変更することで、 `List<Animal>` も　`List<Cat>` も受け取れるメソッドを作ることができます。

```java:Use-site
void printAnimals(List<? extends Animal> animals) { ... } // Covariant
```

```java:Use-site
List<Cat> cats = ...;
printAnimals(cats); // 問題なし（ List<Cat> is a List<? extends Animal> ）
```

#### コンパイル時の型チェック

ところで、 "Hello, Variance!!" で見たように、 `List` が _Covariant_ だと危険なコードがコンパイル時の型チェックをすり抜けてしまう心配がありました。 _Use-site variance annotation_ で `List` を _Covariant_ にするとどうなるのでしょうか。

```java:Use-site
List<Cat> cats = new ArrayList<>();
List<? extends Animal> animals = cats; // CovariantなのでこれはOK
animals.add(new Animal()); // コンパイルエラー
```

上記のコードでは `add` が（実行時ではなく）コンパイルエラーになります。 `List<? extends Animal>` のような _Covariant_ な `List` は、 `add` や `set` など _Covariant_ な `List` が持っているとおかしいメソッドは使えないものとして型チェックが行われます。そのため、 _Use-site variance annotation_ であっても危険なコードがコンパイルをすり抜けてしまうことはありません。

_<span style="font-size: smaller;">※ 実際には、 `add` や `set` などのメソッド自体が利用不可になっているわけではありません。メソッドの引数の型が安全な範囲に限定されているだけで、 `add` メソッドであれば `null` を渡すことはできます。</span>_

Use-site variance annotation の問題点と対処法
--------------------------------------------------------------

これまでに見てきた Declaration-site variance annotation と Use-site variance annotation の利点・欠点についてまとめると次のようになります。

|   | Declaration-site variance annotation | Use-site variance annotation |
|---|---|---|
| 利点 | 宣言時に一度だけ `out`, `in` を書けばいい | より柔軟なケースに対応可能 |
| 欠点 | 対応可能なケースが限定されている | 利用時に毎回 `? extends`, `? super` を書かなければならない |

これだけを見ると一長一短で、どちらが望ましいとは言えないように思えます。しかし、 _Use-site variance annotation_ で利用時に正しく _Variance_ を指定するのは、その型の設計者ではない利用者にとってはとても難しいことです。

### 問題点

冒頭のコードを思い出して下さい。

```java:Use-site（良くない例）
interface Foo {
	Comparator<Integer> getComparator();
}
```

```java:Use-site（良い例）
interface Foo {
	Comparator<? super Integer> getComparator();
}
```

_Variance_ についてきちんと理解していなかったり、注意が足りなかったりすると前者のように書いてしまうのではないでしょうか。

前者が良くないのは `Foo` を継承して次のような `Bar` を作ることができないからです。

```java:Use-site
interface Bar extends Foo {
	Comparator<Number> getComparator(); // オーバーライドして Comparator<Number> を返すようにする。
}
```

`Comparator<Number>` は `Comparator<Integer>` よりも広い型 `Number` に対応できます。もちろん、 `Integer` にも対応できるため、 `getComparator` メソッドの戻り値の型を `Comparator<Number>` でオーバーライドしても問題は起こらないはずです。不必要にそれを禁止してしまうのは良くありません。

これくらいのシンプルな例であれば少し考えれば `? super` を付ければ良いとわかるかもしれません。しかし、より複雑な次の例ではどうでしょうか。次の `qux` メソッドの `Animal` にどのような Annotation を付ければ良いか考えてみて下さい（ `Baz` と `Qux` に意味はありません。純粋に型のみから考えて下さい）。

```java:Use-site
interface Baz<T, U> {
	Supplier<? extends U> baz(Consumer<? super T> consumer);
}

interface Qux {
	Baz<Animal, Animal> qux(); // Baz<Animal, Animal> に適切に Annotation を付けたい
}
```

答えは↓です（説明は後述）。

```java:Use-site
interface Qux {
	Baz<? extends Animal, ? super Animal> qux();
}
```

このように、 _Use-site variance annotation_ で適切な _Annotation_ を考えるのは複雑です。この複雑さこそが、比較的新しい言語で _Use-site variance annotation_ が採用されていない理由だと思います。

### 対処法

とはいえ、 Java を使う以上 _Use-site variance annotation_ と付き合っていかなければなりません。

ここからは僕の考えですが、 _Use-site variance annotation_ を正しく使うには、 __一度 Declaration-site variance annotation として考えてから Use-site variance annotation に変換すると良い__ と思います。

_Declaration-site variance annotation_ で考えるのは難しくありませんし、 _Use-site variance annotation_ に変換するのも簡単です。次の表のような単純なルールで変換できます。

|   | Declaration-site variance annotation | Use-site variance annotation |
|---|---|---|
| 宣言時 | `<out T>`, `<in U>` | `<T>`, `<U>` |
| 利用時 | `<Foo>`, `<Bar>` | `<? extends Foo>`, `<? super Bar>` |

#### Variance がわかっている場合

前述の `Comparator` の例で考えてみます。 `Comparator` の `T` は `compare` メソッドの引数でしか使われていないので `Comparator` は _Contravariant_ だと考えられます。そのため、 `T` には `in` が付与されていると考えます。

```java:Declaration-site
// 宣言時
interface Comparator<in T> {
	int compare(T o1, T o2);
}

// 利用時
interface Foo {
	Comparator<Integer> getComparator();
}
```

これを Use-site variance annotation に変換すると、「宣言時に `in` → 利用時に `? super` 」なので、簡単に次のコードが得られます。

```java:Use-site
// 宣言時
interface Comparator<T> {
	int compare(T o1, T o2);
}

// 利用時
interface Foo {
	Comparator<? super Integer> getComparator();
}
```

これなら、 `in` か `out` かを知っていれば簡単に _Use-site variance annotation_ に変換できます。次のような複雑な型であっても、

```java
interface Foo {
	Supplier<Comparator<Cat>> foo(Function<Consumer<Animal>, List<Animal>> function);	
}
```

_Declaration-site variance annotation_ での宣言を考えると

```java:Declaration-site
interface Supplier<out T> { ... }
interface Consumer<in T> { ... }
interface Function<in T, out R> { ... }

interface Comparator<in T> { ... }

interface List<T> { ... } // T は引数でも戻り値でも使われているので in でも out でもない
```

なので、機械的に Use-site variance annotation に変換できます。

```java:Use-site
interface Foo {
	Supplier<? extends Comparator<? super Cat>> foo(Function<? super Consumer<? super Animal>, ? extends List<Animal>> function);	
}
```

#### Variance がわかっていない場合

`in` か `out` かどちらでもないかわからない場合は、まずは _Variance_ について考えます。

例として、前述の `Baz` について考えてみましょう。

```java:Use-site
interface Baz<T, U> {
	Supplier<? extends U> baz(Consumer<? super T> consumer);
}
```

まずはワイルドカードを外します。

```java:Declaration-site（in、outを付ける前）
interface Baz<T, U> {
	Supplier<U> baz(Consumer<T> consumer);
}
```

一見 `T` は引数で、 `U` は戻り値で使われているように見えますが、 `Consumer` は _Contravariant_ 、 `Supplier` は _Covariant_ です。

- `Consumer<Cat>` > `Consumer<Animal>`
- `Supplier<Cat>` < `Supplier<Animal>`

なので、 `Baz<Cat, Animal>` と　`Baz<Animal, Cat>` で考えると前者の `baz` メソッドはより広い型を受けてより狭い型を返しているので、

- `Baz<Cat, Animal>` < `Baz<Animal, Cat>`

と考えても問題なさそうです。 `T` については `Cat` \< `Animal` と方向が同じなので _Covariant_ 、 `U` は方向が逆なので _Contravariant_ です。つまり、 _Annotation_ を付けると次のようになります。

```java:Declaration-site（in、outを付けた後）
interface Baz<out T, in U> {
	Supplier<U> baz(Consumer<T> consumer);
}
```

ここまでわかれば、機械的に _Use-site variance annotation_ に変換し、利用時には `Baz<? extends Animal, ? super Animal>` とすれば良いことがわかります。

難しいのは、 メソッドの型から _Variance_ を考えただけでは不十分なケースがあることです。

例えば、 Java 8 で導入された `Optional` クラスの主な機能は次の通りで、 `Optional` は _Covariant_ と考えると適切に思えます。

```java:Use-site
class Optional<T> {
	T get() { ... }

	void ifPresent(Consumer<? super T> consumer) { ... }

	<U> Optional<U> map(Function<? super T, ? extends U> mapper) { ... }

	...
}
```

- `Cat` < `Animal`
- `Consumer<Cat>` > `Consumer<Animal>`
- `Function<Cat, U>` > `Function<Animal, U>`
- `Optional<Cat>` < `Optional<Animal>`

しかし、 `Optional` クラスは次のようなメソッドも持っています。

```java:Use-site
T orElse(T other) { ... }
```

このメソッドから考えると `Optional` は `T` について _Invariant_ でなければなりません。しかし、 `Optional` の本質ではないこのメソッドに引きずられて _Invariant_ になってしまうというのも微妙な話です。

僕の考えでは、本来は `orElse` は次のような `static` メソッドとして宣言されているべきだったと思います（もし _Declaration-site variance annotation_ で `Optional` を _Covariant_ として実装するなら `orElse` をこうしなければならなかったはずです）。

```java
static <T> T orElse(Optional<T> optional, T other) { ... }
```

このように、必ずしもその型の持つメソッドだけから既存の型の _Variance_ を判断できるわけではありません。 Java は _Declaration-site variance annotation_ ではないので、設計時にそこまで考慮されずにメソッドが実装されていることがあります。ですので、メソッドの型からだけではなく、その型の持つ本質的な機能まで考えて _Variance_ を考える必要があります。

ただ、実際にはよく使うジェネリックなクラスやインタフェースは限られているので、それらの型パラメータが `in` か `out` かを覚えておけば困ることは少ないと思います。

下に Java の主要なクラス、インタフェースの型パラメータに `in`, `out` を付与したリストを示します。

```java:Declaration-site
Collection<E>
List<E>
Set<E>
SortedSet<E>
Map<K, V>
SortedMap<K, V>
Map.Entry<out K, V>

Iterable<out E>
Iterator<out E>

Comparable<in T>
Comparator<in T>

Optional<out T>

Supplier<out T>
Consumer<in T>
Predicate<in T>
Function<in T, out R>

BiConsumer<in T, in U>
BiPredicate<in T, in U>
BiFunction<in T, in U, out R>

UnaryOperator<T>
BinaryOperator<T>

Stream<out T>
Collector<in T, A, out R>
```

#### ジェネリックな型を自作する場合

主要な型については `in` か `out` かを覚えてしまえばいいですが、自作した型についてはそういうわけにはいきません。

ジェネリックな型を自作する場合は、 `Declaration-site variance annotation` のように型パラメータが `in` なのか `out` なのかどちらでもないのかを意識して設計するのが良いと思います。メソッドの引数や戻り値が `in` や `out` に違反していないか確認して下さい。

僕はわかりやすいように次のようにコメントを付けています。

```java:Use-site
class Foo</*in*/ T, /*out*/ U, V> {
	...
}
```

また、 Java 8 からは型パラメータにアノテーションを付けられるようになったので、[自作ライブラリ](https://github.com/koher/Java-Variance)を使ってアノテーションを付けています。

```java:Use-site
class Foo<@In T, @Out U, V> {
	...
}
```

`in` 、 `out` が決まっていれば使うときは簡単です。

```java:Use-site
Foo<? super String, ? extends Number> getFoo();
```

ただ、宣言したクラスやインタフェースが正しく `in` や `out` を守れているかを検証するのはなかなか難しいです。[前述のライブラリ](https://github.com/koher/Java-Variance)では C# と同様のアルゴリズムによって `@In`, `@Out` による型チェックを行いエラーを報告してくれます。

![@In と @Out の例](https://raw.githubusercontent.com/koher/Variance4J/master/variance4j.png)

#### ? extends や ? super を書かなくても良い場合、書いた方が良い場合

利用時に `out` なら `? extends` を、 `in` なら `? super` を付与すると言っても、さすがにすべてのジェネリック型の変数にワイルドカードを使う必要はないと思います。

```java
Optional<Animal> animal = Optional.ofNullable(...); // Optional<? extends Animal> でなくて良い
```

変数のスコープ内で _Covariant_ や _Contravariant_ であってほしいケースは稀だと思います。変数の型については必要なとき（そうしないとコンパイルが通らないとき）だけ `? extends` や `? super` をつければ良いでしょう。

しかし、メソッドの戻り値や引数、フィールドについては常に `? extends` や `? super` を付けた方が良いでしょう。前述の `Comparator` の例のように、 `? extends` や `? super` を書き忘れると本来問題ないことまで禁止してしまうことになります。

_<span style="font-size: smaller;">※ Java においては、"継承と Variance"で見たように継承してメソッドの引数の型を広げてもオーバーライドではなくオーバーロードとして扱われます。そのため、引数に対して `? extends` や `? super` が必要になるのは、ジェネリックな型がその型パラメータを別のジェネリックな型の型パラメータとして指定する場合だけです（例えば、　`Foo<T>` のメソッドで引数に `Comparator` などのジェネリックな型を指定し、その型パラメータとして `T` を使う場合など）。ただ、それ以外のケースでついていても特に害はないと思います。</span>_

List\<? extends Foo\> はダメ？
--------------------------------------------------------------

_Declaration-site variance annotation_ 的に考えると `List` は _Invariant_ なので `List<? extends Foo>` のように `List` に　`? extends` を付けて使うべきではないということになります。しかし、前述の

```java:Use-site
void printAnimals(List<? extends Animal> animals) { ... }
```

みたいなメソッドを作りたくなったらどうすれば良いでしょうか。

Java にはイミュータブルな `List` を表す型がありません。イミュータブルな `List` もミュータブルな `List` も `List` を共用します。その上で、 `add` や `set` のようなミュータブルな `List` 用のメソッドは optional operation なので、ミュータブルのときだけ実装して下さい（イミュータブルな `List` では `UnsupportedOperationException` をスローして下さい）という設計です。

この設計には苦々しい気持ちになりますが、そうなってしまっているものは仕方ありません。 `add` や `set` が oprional operation と言うのであれば、それらがないイミュータブルな `List` を想定しているケースにおいては `List<? extends Foo>` などとしても良いと思います。

しかし、現実問題としてそういうケースでは大抵 `Iterable` を代わりに使えば事足りるのではないでしょうか。

```java:Use-site
void printAnimals(Iterable<? extends Animal> animals) { ... }
```

`Iterable` は `Iterable<out T>` と考えることができるので、 `? extends` を付けて

```java:Use-site
void printAnimals(Iterable<? extends Animal> animals) { ... }
```

としても問題ありません。

`List<? extends Foo>` を使うのは、すべてを理解した上で、イミュータブルな `List` として使いたい場合で、かつ `Iterable` ではダメなとき（ `get` が使いたいときなど）に限定するのがいいんじゃないでしょうか。

PECSとの比較
--------------------------------------------------------------

__PECS (producer-extends, consumer-super)__ は Java のワイルドカードの使い方に関する有名な戦略です。 `Foo<T>` から `T` を取得して利用する、つまり `Foo` が producer なら `? extends` を、 `Foo<T>` に `T` を渡して処理させる、つまり `Foo` が consumer なら `? super` を付けるというものです。これは、 `in` が引数でしか使えず、 `out` が戻り値でしか使えないことと同じようなことを言っており、その結果はほぼ _Declaration-site variance annotation_ で考えたときと同じになります。

ただ、 _PECS_ は _Use-site variance annotation_ に基づいた考え方であり、一つの型の _Variance_ を利用時に変更することに躊躇がないように思います。例えば、 `Collections` クラスの `copy` メソッドは次のように宣言されています。

```java:Use-site
// src から dest へコピー
static <T> void copy(List<? super T> dest, List<? extends T> src)
```

`dest` は consumer なので `? super`　、 `src` は producer なので `? extends` というわけです。これは前節で述べた考え方とはマッチしません。 `copy` メソッドに関しては利用時に `List` の _Variance_ を変更しなくても、次のような実装をすれば十分ではないかと思います。

```java
// src から dest へコピー
// ただし、 dest が src より短い場合のエラー処理などは省く。
static <T, U extends T> void copy(List<T> dest, List<U> src) {
	ListIterator<T> destIterator = dest.listIterator();
	Iterator<U> srcIterator = src.listIterator();
	while (srcIterator.hasNext()) {
		destIterator.next();
		destIterator.set(srcIterator.next());
	}
}
```

また、 _PECS_ はあくまで利用時の指針であり、ジェネリック型を設計するときには役に立ちません。ジェネリック型を作るときは　_Declaration-site variance annotation_ 的な考え方で、型パラメータごとに `in` にしたいのか `out` にしたいのかを考えないと、 _Variance_ について設計者の意図がよくわからない型ができあがってしまいます。

まとめ
--------------------------------------------------------------

`? super` や `? extends` は Java でジェネリクスを使う上で特に難しい部分です。 C# や Scala 、 Ceylon など比較的新しい言語では、よりシンプルでわかりやすいアプローチが採用されています。

本投稿では、それらの言語で採用された考え方を元に、 Java の `? super` や `? extends` を使う方法を紹介しました。また、そのための前提知識として _Variance（変性）_ の考え方について説明しました。最後に、 Java でよく用いられる _PECS_ という戦略との比較をしました。

色々と調べながら書いた部分も多いので、おかしなところがあればご指摘下さい。

参考文献
--------------------------------------------------------------

1. [Exact rules for variance validity - Eric Lippert's Blog](http://blogs.msdn.com/b/ericlippert/archive/2009/12/03/exact-rules-for-variance-validity.aspx)
2. [Covariance and contravariance (computer science) - Wikipedia](http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29)