Assume the following code:
class ConstructMe<T> {}
data class Test<T> constructor(var supplier: () -> ConstructMe<T>) {}
fun main(args: Array<String>) {
works<Int>()
breaks<Int>()
}
fun <T> works() {
Test<T>({ ConstructMe<T>() }) // (1) any one class type parameter can be removed like:
Test({ ConstructMe<T>() }) // (2) still works (class type inferred by argument type)
Test<T>({ ConstructMe() }) // (3) still works (argument type inferred by class type)
}
fun <T> breaks() {
Test<T>(::ConstructMe) // type interference failed (should probably work like (3); compiler improvement possible?)
Test<T>(::ConstructMe<T>) // type interference failed & type argument not allowed (language change necessary?)
}
I've run into this by passing JavaFX properties (SimpleIntegerProperty
, SimpleStringProperty
, ... and SimpleObjectProperty<T>
) to a generic class constructors () -> Property<T>
argument, where passing ::SimpleIntegerProperty
works without a problem, while ::SimpleObjectProperty
fails like the above example code.
Is it possible to improve the compiler here or to allow passing type parameters to constructor/function references? Does it even make sense to use constructor references over simple lambda expressions here? Does it compile any differently?
Yes, it is possible to improve the compiler here. It could infer type parameter for ConstructMe
. See issue https://youtrack.jetbrains.com/issue/KT-10711.
For non-inline ounter function(in this case it is constructor of Test) there is no difference between lambda and callable reference to constructor. For both cases compiler creates anonymous class which has method invoke
that creates an instance of ConstructMe
.
But callable reference is more convenient than lambda in cases where constructor has a lot of parameters.