Reputation: 1128
If I have
sealed class Foo<A> {
data class Bar<A>(val value: Int): Foo<A>()
}
and I want to refer to the Bar<Int>
constructor as an implicit lambda using the ::
operator, then none of the following are accepted as valid syntax:
Foo<Int>::Bar<Int>
::Foo.Bar<Int>
::(Foo.Bar<Int>)
(the compiler tells me that this syntax is reserved for future use).I can refer to it if I explicitly import the nested class constructor into the scope using
import com.package.Foo.Bar
which allows me to write ::Bar
for the constructor and Bar<Int>::value
for the property getter. But I have to do this for every nested constructor, and it kind of defeats the advantage of using the ::
operator to save typing.
Is there a notation that I have missed which allows me to avoid having to import all nested class names and constructors?
My original example did not involve generics, which turns out was an oversimplification of the problem I had in my actual code that I am working on, which does use generics.
It turns out that for nested classes without generic parameters, the Foo::Bar
notation actually works, so my original question had a false premise. It is, however, not possible to create callable references to constructors within generic classes. This is documented in the following bug report: https://youtrack.jetbrains.com/issue/KT-15952
Upvotes: 1
Views: 189
Reputation: 1128
It is a known bug in the language design: https://youtrack.jetbrains.com/issue/KT-15952
This bug report did however lead me to another workaround using type aliases which is equivalent to adding aliased imports, but has the advantage that you can put the alias where you want, and even share it between modules. In summary, this is the two only viable solutions I know of so far:
// Method one: Import Foo.Bar
import Foo.Bar as BarImported
sealed class Foo<A> {
data class Bar<A>(val value: A): Foo<A>()
}
val ctor: (Int) -> Foo<Int> = ::BarImported
val getter: (BarImported<Int>) -> Int = BarImported<Int>::value
// Method two: Alias Foo.Bar
typealias BarAlias<A> = Foo.Bar<A>
val ctor2: (Int) -> Foo<Int> = ::BarAlias
val getter2: (Foo.Bar<Int>) -> Int = BarAlias<Int>::value
Upvotes: 2