Ulrik Rasmussen
Ulrik Rasmussen

Reputation: 1128

Function reference for class constructor nested within generic parent class

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:

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?

Edit

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

Answers (2)

Ulrik Rasmussen
Ulrik Rasmussen

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

michpohl
michpohl

Reputation: 1115

What about wild card imports?

import com.package.Foo.*

Upvotes: 1

Related Questions