如何将扩展名转换为成员?

时间:2019-01-11 23:36:21

标签: kotlin

Kotlin允许您扩展泛型类型类的具体实例。例如,假设我具有以下类Foo,具有扩展功能Foo<Int>.bar()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()
}

是否可以在没有扩展功能的情况下实现此行为,如果可以,如何将扩展功能转换为成员?是否可以不重命名或更改类型签名?

3 个答案:

答案 0 :(得分:1)

您可以使用 reified 通用参数创建 inline 成员函数:

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>()
}

但是扩展函数在您的情况下更好:它们是类型安全的,更简洁和可读的。

答案 1 :(得分:1)

否,这是不可能的(当前接受的答案与您的代码完全不一样)。

答案 2 :(得分:1)

使用反射,您不必自己在类型和属性之间进行映射。

成员函数propertyValue()将返回具有通用参数或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

您当然可以扩展此功能,以便为您提供所需类型T的所有属性的值(例如,如果您有多个Int属性)。