问题
I am not able to understand and I couldn't find the meaning of out keyword in kotlin.
You can check example here:
List<out T>
If any one can explain the meaning of this. It would be really appreciated.
回答1:
With this signature:
List<out T>
you can do this:
val doubleList: List<Double> = listOf(1.0, 2.0)
val numberList: List<Number> = doubleList
which means T is covariant:
when a type parameter T of a class C is declared out, C<Base> can safely be a supertype of C<Derived>.
This is contrast with in, e.g.
Comparable<in T>
you can do this:
fun foo(numberComparable: Comparable<Number>) {
val doubleComparable: Comparable<Double> = numberComparable
// ...
}
which means T is contravariant:
when a type parameter T of a class C is declared in, C<Derived> can safely be a supertype of C<Base>.
Another way to remember it:
Consumer in, Producer out.
see Kotlin Generics Variance
-----------------updated on 4 Jan 2019-----------------
For the "Consumer in, Producer out", we only read from Producer - call method to get result of type T; and only write to Consumer - call method by passing in parameter of type T.
In the example for List<out T>, it is obvious that we can do this:
val n1: Number = numberList[0]
val n2: Number = doubleList[0]
So it is safe to provide List<Double> when List<Number> is expected, hence List<Number> is super type of List<Double>, but not vice versa.
In the example for Comparable<in T>:
val double: Double = 1.0
doubleComparable.compareTo(double)
numberComparable.compareTo(double)
So it is safe to provide Comparable<Number> when Comparable<Double> is expected, hence Comparable<Double> is super type of Comparable<Number>, but not vice versa.
回答2:
List<out T> is like List<? extends T> in Java
and
List<in T> is like List<? super T> in Java
For example in Kotlin you can do things like
val value : List<Any> = listOf(1,2,3)
//since List signature is List<out T> in Kotlin
回答3:
Refer to thie manual of kotlin
The Kotlin
List<out T>type is an interface that provides read only operations like size, get and so on. Like in Java, it inherits fromCollection<T>and that in turn inherits fromIterable<T>. Methods that change the list are added by theMutableList<T>interface. This pattern holds also forSet<out T>/MutableSet<T>andMap<K, outV>/MutableMap<K, V>
And this,
In Kotlin, there is a way to explain this sort of thing to the compiler. This is called declaration-site variance: we can annotate the type parameter T of Source to make sure that it is only returned (produced) from members of
Source<T>, and never consumed. To do this we provide the out modifier:> 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 > // ... }The general rule is: when a type parameter
Tof a classCis declared out, it may occur only in out-position in the members ofC, but in returnC<Base>can safely be a supertype ofC<Derived>.In "clever words" they say that the class
Cis covariant in the parameterT, or thatTis a covariant type parameter. You can think of C as being a producer of T's, and NOT a consumer ofT's. The out modifier is called a variance annotation, and since it is provided at the type parameter declaration site, we talk about declaration-site variance. This is in contrast with Java's use-site variance where wildcards in the type usages make the types covariant.
来源:https://stackoverflow.com/questions/44298702/what-is-out-keyword-in-kotlin