Kotlin通用约束-要求参数与其他参数类型相同

时间:2019-02-20 05:44:09

标签: kotlin

假设我有两个像这样的pojo:

data class Test (
    var id : Long? = null
)

data class TestOther (
    var id : Long = 0,
    var isCool : Boolean = false
}

然后我有一个像这样的中缀函数:

infix fun <T : Any?> KProperty<T>.equal(rhs : KProperty<T>) = BinaryExpression<Boolean>(this, rhs, EQUALS)

然后这可以按我期望的那样很好地工作:

Test::id equal TestOther::id

但是这样做也是,因为T是所有扩展Any?的类型:

Test::id equal TestOther::isCool

总有一种方法可以指定通用约束,以便可以比较可为空和不能为空的类型,但是不同类型的对象不能不必为每种可能的具体类型都指定重载?

1 个答案:

答案 0 :(得分:2)

目前无法执行。您可以关注此问题以获取更多详细信息 JSON API docs

我在这里看到一种解决方法(类似于该问题中的解决方法)。这个想法是将KProperty<R>包装到包装类中而无差异。如您所见,KProperty类型具有out R的方差,在示例中与我们相反。您可以点击链接以获取有关Kotlin中声明方差异的详细信息 https://youtrack.jetbrains.com/issue/KT-13198

解决方法按预期的那样严格

class KWrapper<R>(val p : KProperty<R>)
infix fun <T : KWrapper<R>, R> T.equal(rhs : T) = false
val <T> KProperty<T>.wrap get() = KWrapper(this)

val a = Test::id.wrap equal TestOther::id.wrap //fails: Long vs Long?
val b = Test::id.wrap equal Test::id.wrap //works
val c = Test::id.wrap equal TestOther::isCool.wrap // fails Long vs Boolean

缺点是您需要分别为左右参数使用.wrap扩展属性(或扩展功能)