How to convert an extension into a member?

Viewed 103

Kotlin allows you to extend concrete instances of a generically typed class. For example, suppose I have the following class Foo, with extension functions Foo<Int>.bar() and Foo<String>.bar():

class Foo<T>(t: T) {
  val a: String = "bar"
  val b: Int = 111
}

fun Foo<Int>.bar() = a
fun Foo<String>.bar() = b

fun main(args: Array<String>) {
  val stringBar: String = Foo(1).bar()
  val intBar: Int = Foo("").bar()
}

Is it possible to achieve this behavior without extension functions, and if so, how do I convert the extension functions into members? Is it possible without renaming or changing the type signatures?

3 Answers

You can create inline member function with reified generic parameter:

class Foo<T>(t: T) {
    val a: String = "bar"
    val b: Int = 111

    inline fun <reified T, E> member(): E? {
        var r: E? = null
        when(T::class) {
            String::class -> r = b as E
            Int::class -> r = a as E
        }
        return r
    }
}

fun main(args: Array<String>) {
   val str = Foo(1).member<Int, String>()
   val i = Foo("").member<String, Int>()
}

But extension functions are better in your case: they are type-safe, more concise and readable.

No, it isn't possible (the currently accepted answer doesn't behave at all similarly to your code).

Using reflection you don't have to do the mapping between type and property by yourself.

The member function propertyValue() will return the value of the first property which has the type of the generic parameter or null.

class Foo {
    val a: String = "bar"
    val b: Int = 111

    inline fun <reified T> propertyValue() = Foo::class.memberProperties.firstOrNull {
        it.returnType == T::class.createType()
    }?.get(this)
}

Foo().propertyValue<Int>()) // 111
Foo().propertyValue<String>()) // bar
Foo().propertyValue<Double>()) // null

You could of course extend this function so it would give you the values of all properties of the desired type T (if you have multiple Int properties for example).

Related