问题
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, out
V>/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
T
of a classC
is 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
C
is covariant in the parameterT
, or thatT
is 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