Я не можу зрозуміти і не зміг знайти значення ключового слова out у kotlin.
Ви можете перевірити приклад тут:
List<out T>
Якщо хтось може пояснити значення цього. Це було б дуже вдячне.
Відповіді:
З цим підписом:
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> .
Ще один спосіб запам’ятати це:
Споживач в , продюсер від'їзду .
----------------- оновлено 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>
, але не навпаки.
out
Частина не є тим, що робить List
незмінним. Ви можете легко створити власний List<out T>
інтерфейс, який має clear()
метод, оскільки для цього не потрібні аргументи.
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
Зверніться до цього посібника з 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, коли символи підстановки у звичаях типу роблять типи коваріантними.
Запам'ятайте так:
in
є "для в путах» - ви хочете помістити (запис) що - то в нього (так що це «споживач»)
out
це "за вихід пут» - ви хочете взяти (прочитати) що - то з нього (так що це «продюсер»)
Якщо ви з Java,
<in T>
це для введення, так це як <? super T>
(споживач)
<out T>
для випуску, так що це як <? extends T>
(виробник)
List<out T>
декларованої декларації є те, щоout
робить її незмінною (порівняно зі змінними колекціями, які не мають). Це може допомогти згадати та підкреслити це у відповіді. Неявна передача є наслідком цього, а не головного моменту (оскільки не можна писати в List <Number>, безпечно мати його як посилання на List <Double>).