Declaration-Site and Use-Site Variance
Using <out T>
in a type declaration, as List
does, is called “declaration-site variance”. The alternative is “use-site variance” — using <out T>
for a function parameter.
For example, let’s try to clone some frogs:
open class Animal
class Frog : Animal()
class Axolotl : Animal()
fun <T> clone(input: MutableList<T>, output: MutableList<T>) {
input.forEachIndexed { index, item -> output[index] = item}
}
fun main() {
val input = mutableListOf(Frog(), Frog())
val result = mutableListOf<Animal>(Axolotl(), Axolotl())
clone(input, result)
println(result)
}
clone()
takes in two lists, and it assigns the values in the output list to be the same as the input list, on a per-index basis. This function should be performing some data validation, ensuring that the output list is the same length or longer than the input list, but we are skipping that to keep the example code shorter.
However, this code does not compile:
Type mismatch: inferred type is Animal but Frog was expected
The complaint is about the input
parameters to clone()
. We are passing into clone()
:
- A
List<Frog>
, as that is whatmutableListOf(Frog(), Frog())
returns - A
List<Animal>
, as that is what we specifiedresult
to be
However, clone()
is expecting both parameters to be of type T
, but we are passing in two different (but related) types: Frog
and Animal
.
Logically, what we want clone()
to do is fine. A Frog
is an Animal
, so we can take a bunch of Frog
objects and assign them to Animal
slots in a list.
Adding out
to the use site indicates that we can accept the input
MutableList
to be of type T
or any sub-type:
open class Animal
class Frog : Animal()
class Axolotl : Animal()
fun <T> clone(input: MutableList<out T>, output: MutableList<T>) {
input.forEachIndexed { index, item -> output[index] = item}
}
fun main() {
val input = mutableListOf(Frog(), Frog())
val result = mutableListOf<Animal>(Axolotl(), Axolotl())
clone(input, result)
println(result)
}
That satisfies the compiler and makes logical sense: we can put an object of any Animal
sub-type into an Animal
slot in a list.
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.