What is out keyword in kotlin

心已入冬 提交于 2020-08-20 18:07:17

问题


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 from Collection<T> and that in turn inherits from Iterable<T>. Methods that change the list are added by the MutableList<T> interface. This pattern holds also for Set<out T>/MutableSet<T> and Map<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 class C is declared out, it may occur only in out-position in the members of C, but in return C<Base> can safely be a supertype of C<Derived>.

In "clever words" they say that the class C is covariant in the parameter T, or that T is a covariant type parameter. You can think of C as being a producer of T's, and NOT a consumer of T'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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!