дженерики kotlin только для потребителей - PullRequest
0 голосов
/ 05 сентября 2018

Позвольте мне сказать, что у меня есть этот пример Java:

interface Sink<T> {
    void accumulate(T t);
}

public static <T> void drainToSink(Collection<T> collection, Sink<? super T> sink) {
    collection.forEach(sink::accumulate);
}

Обратите внимание, как второй параметр объявлен как ? super T. Мне это нужно, потому что я хочу вызвать этот метод так:

Sink<Object> sink = .... // some Sink implementation
Collection<String> strings = List.of("abc");
drainToSink(strings, sink);

Теперь я пытаюсь добиться того же с помощью kotlin (с которым у меня очень небольшой опыт):

interface Sink<T> {
    fun accumulate(t: T)
}

fun <T> drainToSink(collection: List<T>, sink: Sink<T>) {
   ....
}

А сейчас я пытаюсь использовать это:

fun main(args: Array<String>) {

     val sink = object : Sink<Any> {
         override fun accumulate(any: Any) {  }
     }

     val strings = emptyList<String>()
     drainToSink(strings, sink)
}

Интересно, что это не сбоит (если я не знаю слишком мало о kotlin здесь).

Я действительно ожидал, что мне нужно добавить в объявление что-то вроде Sink<in T>, чтобы компилятор знал, что это на самом деле просто a Consumer или in T всегда включен, по умолчанию

Может ли кто-то, кто знает kotlin лучше меня, указать мне правильное направление?

1 Ответ

0 голосов
/ 05 сентября 2018

Как я уже сказал в своем комментарии, T здесь выводится как Any. Это то, что я вижу, когда разрешаю моей IDE добавлять явные аргументы типа к вызову drainToSink.

Поскольку kotlin's List является строго продюсером, поскольку он неизменен, он объявляет свой параметр типа как out E. Вы получаете List<Any> в качестве типа параметра для drainToSink, и можно присвоить List<String> этому:

val strings = emptyList<String>()
val x: List<Any> = strings // works

Если вы измените первый тип параметра на MutableList<T>, у которого нет параметра ковариантного типа, ваш пример не завершится неудачей:

fun <T> drainToSink(collection: MutableList<T>, sink: Sink<T>) {
    ....
}
val strings = emptyList<String>()
drainToSink(strings, sink) // type mismatch: Required: MutableList<Any>, Found: List<String>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...