Let' say i have this java example:
interface Sink<T> {
void accumulate(T t);
}
public static <T> void drainToSink(Collection<T> collection, Sink<? super T> sink) {
collection.forEach(sink::accumulate);
}
Notice how the second parameter is declared to be ? super T. I need this because I want to call that method like this:
Sink<Object> sink = .... // some Sink implementation
Collection<String> strings = List.of("abc");
drainToSink(strings, sink);
Now I am trying to achieve the same thing with kotlin (which I have very small experience with):
interface Sink<T> {
fun accumulate(t: T)
}
fun <T> drainToSink(collection: List<T>, sink: Sink<T>) {
....
}
And now I am trying to use it:
fun main(args: Array<String>) {
val sink = object : Sink<Any> {
override fun accumulate(any: Any) { }
}
val strings = emptyList<String>()
drainToSink(strings, sink)
}
Interestingly enough, this does not fail (unless I know too little about kotlin here).
I was really expecting that I need to add to the declaration something like Sink<in T> to let the compiler know that this is actually just a Consumer, or is in T always on, by default?
Can someone who knows kotlin better than me, point me in the right direction?
Like I said in my comment,
Tis being inferred asAnyhere. That's what I see when letting my IDE add explicit type arguments to thedrainToSinkcall.Since kotlin's
Listis strictly a producer, because it is immutable, it declares it's type parameter asout E. You getList<Any>as a parameter type fordrainToSink, and it's fine to assign aList<String>to that:If you change the first parameter type to
MutableList<T>, which does not have a covariant type parameter, your example does fail: