liveBook · Manning

Use-site variance

As explained in Kotlin in Action, 2E

Use-site variance specifies a variance constraint for a particular occurrence of a generic type parameter rather than for its declaration.

Use-site variance applies a variance constraint to one occurrence of a generic type, rather than changing the generic class declaration. Kotlin uses it when a particular parameter is only read from or only written to, and it corresponds to Java wildcards such as ? extends and ? super. section 11.0 section 11.3.5

Copying from a producer

fun <T> copyData(source: MutableList<out T>, destination: MutableList<T>) { for (item in source) { destination.add(item) } } The `out T` projection makes `source` readable as a producer of `T`. The function can therefore copy values from a more specific collection into a destination collection of the chosen type, even though `MutableList` is invariant in general. section 11.3.5

Choose the projection according to how the occurrence is used:

  • `MutableList<out T>` permits reading values as `T`, but prevents adding values because the precise element type is unknown. section 11.3.5
  • `MutableList<in T>` permits writing `T` values into the destination while hiding the specific supertype used by that collection. section 11.3.5
  • A function can instead use two type parameters, such as `<T: R>`, to copy a subtype collection into a supertype collection without projections. section 11.3.5
Listing 11.16 A data copy function with an out-projected type parameter
fun <T> copyData(source: MutableList<out T>,      #1
                 destination: MutableList<T>) {
    for (item in source) {
        destination.add(item)
    }
}

Inspect the compact Kotlin implementation that projects the source list with `out`. section 11.3.5

Declaration-site variance is usually more concise because a class declares its variance once. Use-site variance remains useful when a generally invariant type, such as `MutableList`, has a producer or consumer role at one particular call site. section 11.3.5

How Kotlin in Action, 2E covers it

How deep it goes
Explains declaration syntax, copy-function applications, projections, and prohibited writes without descending into compiler internals.
Examples
Uses Kotlin copy functions, mutable integer and `Any` lists, and an invalid write to an out-projected list.
What it assumes
Assumes generic type parameters and distinguishes use-site variance from declaration-site variance.
What you can do after
Apply it via Kotlin `in` and `out` projections when generic parameters need local producer or consumer constraints.
How it connects
Connects use-site variance to generics, declaration-site variance, Java wildcards, covariance, and contravariance.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Kotlin in Action, 2E. The section links point to the parts of the book it draws on.