如何链接两个Kotlin函数参数的泛型类型?

时间:2016-10-01 22:55:26

标签: generics kotlin

我想写点像

fun <T, R> check(thing: T, property: KProperty1<T, R>, value: R) = 
    property.get(thing) == value

这样

assertTrue(check("Hello", String::length, 5))

assertTrue(check("Hello", String::length, "banana"))

没有编译。

1 个答案:

答案 0 :(得分:4)

这似乎是Kotlin类型推断的一个问题(不管它是一个bug还是设计,我都不知道)。例如,如果类型是显式的,则不会编译:

check<String, Int>("Hello", String::length, "banana")

它可能设计为像Java的通用方法类型推断一样工作,因为编译器为两个参数推断出RT的公共超类型。见Why doesn't type argument inference fail when I provide inconsistent method arguments?

根据上面的帖子,在Java 5,6和7中你可能会声明它像

fun <T, R, R1: R> check(thing: T, property: KProperty1<T, R>, value: R1) = 
    property.get(thing) == value

并且使用不一致的params的调用将无法编译(我还没有尝试过)。但是,这被认为是一个错误,在Java 8中,不一致的params的调用仍在编译(我试过了)。

在任何情况下,您都可以将它包装在一个类中以避免推理并将类型参数绑定在一起:

class Checker<T, R>(val property: KProperty1<T, R>)  {
  fun check(thing: T, value: R) =
    property.get(thing) == value
}
assertTrue(Checker(String::length).check("Hello", 5))
// does not compile
assertTrue(Checker(String::length).check("Hello", "banana"))