Johann Pardanaud
05/09/2023, 2:45 PMout
since the get()
accepts this same type as a parameter:
interface MyInterface<T> {
val inner: T
fun get(other: T): String
}
I want this interface to be iterable when the generic type is also an iterable, so I add this extension function:
operator fun <T> MyInterface<Iterable<T>>.iterator(): Iterator<T> = TODO()
However, when using this interface, I cannot iterate over it:
fun doSomething(payload: MyInterface<Set<Any>>) {
for (row in payload) { /* ... */ }
^ COMPILE ERROR: For-loop range must have an 'iterator()' method
}
If I declare the generic type as out
, the compiler no longer complains about a missing iterator()
method, but the MyInterface::get(T)
method cannot compile anymore since the generic type is out
(while also used as an in
by this method).
From what I understand, it seems that Kotlin accepts to iterate over a type even if it doesn’t explicitly implement the Iterable<T>
interface, as long as an iterator(): Iterator<T>
method exists. However, it doesn’t seem to work when the generic type is not defined as out
, despite being both in
and out
here in my first example.
Am I missing/abusing something or is this a bug in the language?Sam
05/09/2023, 2:53 PMoperator fun <T, I: Iterable<T>> MyInterface<I>.iterator(): Iterator<T> = TODO()
Sam
05/09/2023, 2:53 PMSam
05/09/2023, 2:53 PMJohann Pardanaud
05/09/2023, 2:55 PMJohann Pardanaud
05/09/2023, 2:55 PMJohann Pardanaud
05/09/2023, 2:55 PMJohann Pardanaud
05/09/2023, 2:56 PMJohann Pardanaud
05/09/2023, 3:01 PMSam
05/09/2023, 3:10 PMMyInterface<Iterable<T>>
says that the type must be exactly Iterable<T>
, whereas MyInterface<I>
where I: Iterable<T>
is one way to say it can be any subtype of Iterable<T>
.Sam
05/09/2023, 3:10 PMoperator fun <T> MyInterface<out Iterable<T>>.iterator(): Iterator<T> = TODO()
Sam
05/09/2023, 3:19 PMin
and `out`”, but I think that might indicate a misunderstanding. If a type is used only as an input, it can have in
variance, and if it’s used only as an output, it can have out
variance, but if it’s used as both an input and an output, it cannot have any variance (i.e. it’s neither in nor out). That’s the default, if variance is not specified.Johann Pardanaud
05/09/2023, 3:51 PM