Що таке ключове слово у kotlin


85

Я не можу зрозуміти і не зміг знайти значення ключового слова out у kotlin.

Ви можете перевірити приклад тут:

List<out T>

Якщо хтось може пояснити значення цього. Це було б дуже вдячне.

Відповіді:


58

З цим підписом:

List<out T>

Ви можете зробити це:

val doubleList: List<Double> = listOf(1.0, 2.0)
val numberList: List<Number> = doubleList

що означає Т є коваріантним :

коли тип параметра T з класу C оголошується поза , С <База> може безпечно бути супертіп з C <Derived> .

Це контраст із in , напр

Comparable<in T>

Ви можете зробити це:

fun foo(numberComparable: Comparable<Number>) {
  val doubleComparable: Comparable<Double> = numberComparable
  // ...
}

що означає, що T є противаріантною :

коли тип параметра T з класу C оголошується в , C <Derived> може безпечно бути супертіп з C <Base> .

Ще один спосіб запам’ятати це:

Споживач в , продюсер від'їзду .

див. Kotner Generics Variance

----------------- оновлено 4 січня 2019 р. -----------------

Щодо " Споживач входить, виробник виходить ", ми читаємо лише у Producer - метод виклику, щоб отримати результат типу T; і писати лише споживачеві - метод виклику, передаючи параметр типу T.

У прикладі для List<out T>, очевидно, що ми можемо зробити це:

val n1: Number = numberList[0]
val n2: Number = doubleList[0]

Тож безпечно надавати, List<Double>коли List<Number>це очікується, отже, List<Number>це супер типList<Double>, але не навпаки.

У прикладі для Comparable<in T>:

val double: Double = 1.0
doubleComparable.compareTo(double)
numberComparable.compareTo(double)

Тож безпечно надавати, Comparable<Number>коли Comparable<Double>очікується, отже, Comparable<Double>це супер тип Comparable<Number>, але не навпаки.


1
Я думаю, що найважливішим моментом для однієї List<out T>декларованої декларації є те, що outробить її незмінною (порівняно зі змінними колекціями, які не мають). Це може допомогти згадати та підкреслити це у відповіді. Неявна передача є наслідком цього, а не головного моменту (оскільки не можна писати в List <Number>, безпечно мати його як посилання на List <Double>).
мінськ

39
Вибачте, але все одно не міг зрозуміти.
Акшай Тару

2
@minsk outЧастина не є тим, що робить Listнезмінним. Ви можете легко створити власний List<out T>інтерфейс, який має clear()метод, оскільки для цього не потрібні аргументи.
Нік Лоуері

це одна з тих тем, яку ви, мабуть, хочете отримати, поки вона вам справді не потрібна десь у вашому коді.
lasec0203

109
List<out T> is like List<? extends T> in Java

і

List<in T> is like List<? super T> in Java

Наприклад, у Котліні ви можете робити такі речі

 val value : List<Any> = listOf(1,2,3)
//since List signature is List<out T> in Kotlin

4

Зверніться до цього посібника з Kotlin

Тип Kotlin List<out T>- це інтерфейс, який забезпечує операції лише для читання, такі як size, get тощо. Як і в Java, він успадковує від, Collection<T>а той, у свою чергу, успадковує від Iterable<T>. Методи, що змінюють список, додаються MutableList<T>інтерфейсом. Ця закономірність також застосовується для Set<out T>/MutableSet<T>іMap<K, out V>/MutableMap<K, V>

І це,

У Котліні є спосіб пояснити подібні речі компілятору. Це називається дисперсією сайту декларації: ми можемо анотувати параметр типу T Source, щоб переконатися, що він повертається (створюється) від членів Source<T>та ніколи не споживається. Для цього ми пропонуємо модифікатор out:

> 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
>     // ... }

Загальне правило: коли параметр типу T типу класу Cоголошений, він може мати місце лише поза положенням членів C, але у відповідьC<Base> може бути безпечним надтипом C<Derived>.

У "розумних словах" вони кажуть, що клас Cє коваріантним у параметрі T, або Tце параметр коваріантного типу. Ви можете думати про С як про виробника Т, а НЕ про споживача T. Модифікатор out називається анотацією дисперсії, і оскільки він надається на сайті декларації параметру типу, ми говоримо про дисперсію сайту декларації. Це на відміну від розбіжностей між сайтами використання Java, коли символи підстановки у звичаях типу роблять типи коваріантними.


3

Запам'ятайте так:

inє "для в путах» - ви хочете помістити (запис) що - то в нього (так що це «споживач»)

outце "за вихід пут» - ви хочете взяти (прочитати) що - то з нього (так що це «продюсер»)

Якщо ви з Java,

<in T> це для введення, так це як <? super T> (споживач)

<out T>для випуску, так що це як <? extends T>(виробник)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.