[Java, Kotlin] Type Variance

## invariant
```java
// Java
interface Collection<E> ... {
    void addAll(Collection<E> items);
}

void copyAll(Collection<Object> to, Collection<String> from) {
    to.addAll(from); // !!! Would not compile with the naive declaration of addAll
}
```

`Collection<String>` is not a subtype of `Collection<Object>`

## covariant
- lower to upper
- producer

### Java: Use-site variance; Kotlin: Type projections
```java
// Java
interface Collection<E> ... {
    void addAll(Collection<? extends E> items);
}

void copyAll(Collection<Object> to, Collection<String> from) {
    to.addAll(from); // OK!
}
```
assign an instance of `Collection<String>` to `Collection<? extends Object>`
**read** `E` from **Producer** `Collection<? extends E> items`

```kotlin
// Kotlin
class Array<T>(val size: Int) {
    fun get(index: Int): T { /* ... */ }
    fun set(index: Int, value: T) { /* ... */ }
}

fun copy(from: Array<out Any>, to: Array<Any>) {
    assert(from.size == to.size)
    for (i in from.indices)
        to[i] = from[i]
}

val ints: Array<Int> = arrayOf(1, 2, 3)
val any = Array<Any>(3) { "" } 
copy(ints, any)
```
assign an instance of `Array<Int>` to `Array<out Any>`
`from: Array<out Any>` only with get function

### Declaration-site variance
```kotlin
// Kotlin
abstract class Source<out T> {
    abstract fun nextT(): T
}

fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs // This is OK, since T is an out-parameter
    // ...
}
```
assign an instance of `Source<String>` to `Source<Any>`
`objects: Source<Any>` **Producer out** `Any`


## contravariant
- upper to lower
- consumer

### Java: Use-site variance; Kotlin: Type projections
```java
// Java
List<Animal> animals = new ArrayList<>();
List<? super Cat> cats = animals;
cats.add(new Cat());
```
assign an instance of `List<Animal>` to `List<? super Cat>`
**write** `Cat` to **Consumer** `List<? super Cat> cats`

```kotlin
// Kotlin
class Array<T>(val size: Int) {
    fun get(index: Int): T { /* ... */ }
    fun set(index: Int, value: T) { /* ... */ }
}

fun fill(dest: Array<in String>, value: String) {
    // ...
}
```
assign an instance of `Array<CharSequence>` or `Array<Any>` to `Array<in String>`
`dest: Array<in String>` only with set function


### Declaration-site variance
```kotlin
// Kotlin
abstract class Comparable<in T> {
    abstract fun compareTo(other: T): Int
}

fun demo(x: Comparable<Number>) {
    x.compareTo(1.0) // 1.0 has type Double, which is a subtype of Number
    // Thus, we can assign x to a variable of type Comparable<Double>
    val y: Comparable<Double> = x // OK!
}
```
assign an instance of `Comparable<Number>` to `Comparable<Double>`
`y: Comparable<Double>` **Consumer in** `Double`

## Declaration-site to Use-site variance
```java
interface Comparator<in T> {
    int compare(T o1, T o2);
}

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

`in T` -> **contravariant**
upper `Comparator<Integer>` -> lower `Comparator<? super Integer>`

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

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

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

lower `Consumer<? super T>` -> upper `Consumer<T>`
**covariant** -> `out T`

upper `Supplier<? extends U>` -> lower `Supplier<U>`
**contravariant** -> `in U`

```java
interface Baz<out T, in U> {
    Supplier<U> baz(Consumer<T> consumer);
}
```

## Array
### Java
**covariant**

```java
Apple[] apples = new Apple[10];
Fruit[] fruits = apples;
fruits[0] = new Orange(); // throws an exception at runtime (ArrayStoreException or ArrayTypeMismatchException, respectively)
Apple apple = apples[0];
```

### Kotlin
**invariant**
ensures compile time safety and prevents runtime errors

## ref.
- [Generics](http://kotlinlang.org/docs/reference/generics.html)
- [Generic Types and Variance in Kotlin compared to Java](https://proandroiddev.com/basics-what-is-variance-e509378ca37a)
- [Javaの "? extends" や "? super" の使い方をC#やScala風に考える](http://qiita.com/koher/items/7dea63e0ce52ebda9873)
- [Declaration-site and use-site variance explained](https://schneide.wordpress.com/2015/05/11/declaration-site-and-use-site-variance-explained/)
- [型態變異與PECS](https://www.ithome.com.tw/voice/116987)