Java:
public class JavaClass implements ModelController.Callback {
@Override
public void onModelsLoaded(@NonNull List<? extends Model> models) {
doSomething(models);
}
private void doSomething(List<Model> models) { }
}
Kotlin:
class ModelController {
var callback = WeakReference<Callback>(null)
interface Callback {
fun onModelsLoaded(models: List<Model>)
}
fun someFunction() {
callback.get().onModelsLoaded(ArrayList<Model>())
}
}
interface Model {
}
Without the ? extends Model in the Java onModelsLoaded method, the override doesn’t match the interface made in Kotlin. With it, I get the following error:
doSomething(<java.util.List<com.yada.Model>) cannot be applied to (java.util.List<capture<? extends com.yada.Model>>)
Why is the wildcard capture required and why doesn't it allow it to be used against the non-wildcard method?
The issue stems from Kotlin collections being variant, and Java only having use-site variance which is implemented though wildcards (capture is something connected to wildcards but not exactly the ? extends ...
syntax itself).
When in Kotlin we say List<Model>
it means "read-only list of Model
or subtypes of Model
", when we say the same in Java it means "mutable list of exactly Model
and nothing else". To mean roughly what Kotlin's List<Model>
means, in Java we have to say List<? extends Model>
, this is why for the override to work you have to add the wildcard into the Java code.
Now, your doSomething
is written in Java and says that it wants "a list of exactly Model
", and when you are giving it "a list of Model
or its subtypes", the Java compiler complains, because it can be dangerous: doSomething
might try to do something that is not legitimate for a list of, say, ModelImpl
, because it thinks it's working on a list of Model
.
As of now (Kotlin Beat 2), you have two options:
MutableList<Model>
in your Kotlin code - this mean exactly what Java's List<Model>
means, ordoSomething
so that it takes List<? extends Model>
, which is what your current Kotlin code means.In the next update of Kotlin we'll add an annotation on types to facilitate a somewhat cleaner workaround for this problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With