Horje

Kotlin - Generics
Start
  Declaration-site variance

Declaration-site variance (opens new window) can be thought of as declaration of use-site variance once and for all the use-sites.


 class Consumer<in T> { fun consume(t: T) { ... } }

  fun charSequencesConsumer() : Consumer<CharSequence>() = ...

  val stringConsumer : Consumer<String> = charSequenceConsumer() // OK since in-projection
  val anyConsumer : Consumer<Any> = charSequenceConsumer() // Error, Any cannot be passed
  
  val outConsumer : Consumer<out CharSequence> = ... // Error, T is `in`-parameter

Widespread examples of declaration-site variance are List<out T>, which is immutable so that T only appears as the return value type, and Comparator<in T>, which only receives T as argument.

  Use-site variance

Use-site variance (opens new window) is similar to Java wildcards:

Out-projection:


 val takeList : MutableList<out SomeType> = ... // Java: List<? extends SomeType>

  val takenValue : SomeType = takeList[0] // OK, since upper bound is SomeType

  takeList.add(takenValue) // Error, lower bound for generic is not specified

In-projection:


 val putList : MutableList<in SomeType> = ... // Java: List<? super SomeType>
  
  val valueToPut : SomeType = ...
  putList.add(valueToPut) // OK, since lower bound is SomeType

  putList[0] // This expression has type Any, since no upper bound is specified

Star-projection


 val starList : MutableList<*> = ... // Java: List<?>

  starList[0] // This expression has type Any, since no upper bound is specified
  starList.add(someValue) // Error, lower bound for generic is not specified

See also:

  • [Variant Generics](https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#variant-generics) interoperability when calling Kotlin from Java.
  • Syntax

    • class ClassName<TypeName>
    • class ClassName<*>
    • ClassName<in UpperBound>
    • ClassName<out LowerBound>
    • class Name<TypeName:UpperBound>

    Parameters

    Parameter Details
    TypeName Type Name of generic parameter
    UpperBound Covariant Type
    LowerBound Contravariant Type
    ClassName Name of the class

    Remarks

    Implied Upper Bound is Nullable

    In Kotlin Generics, the upper bound of type parameter T would be Any?. Therefore for this class:

    class Consumer<T>
    
    

    The type parameter T is really T: Any?. To make a non-nullable upper bound, explicitly specific T: Any. For example:

    class Consumer<T: Any>
    
    

    Read Article
    https://develop.horje.com/learn/1434/reference