我想在泛型类型T上编写扩展方法,其中匹配类型约束方法参数。
我想要编译:
"Hello".thing("world")
但不是这样,因为42不是字符串:
"Hello".thing(42)
此定义不起作用,因为Any
fun <T> T.thing(p: T) {}
答案 0 :(得分:12)
正如@Alexander Udalov所述,它不可能直接执行,但有一种解决方法,您可以在其他类型上定义扩展方法,如下所示:
data class Wrapper<T>(val value: T)
val <T> T.ext: Wrapper<T> get() = Wrapper(this)
fun <T> Wrapper<T>.thing(p: T) {
println("value = $value, param = $p")
}
通过以上编译:
"abc".ext.thing("A")
但下一次失败
"abc".ext.thing(2)
使用:
Kotlin: Type inference failed: Cannot infer type parameter T in fun <T> Wrapper<T>.thing(p: T): Unit
None of the following substitutions
receiver: Wrapper<String> arguments: (String)
receiver: Wrapper<Int> arguments: (Int)
can be applied to
receiver: Wrapper<String> arguments: (Int)
根据@hotkey的建议,似乎应该可以避免使用具有以下扩展属性的显式Wrapper
类型:
val <T> T.thing: (T) -> Any? get() = { println("extension body") }
然后将其用作"abc".thing("A")
,但也会失败。令人惊讶的是,以下编译"abc".thing.invoke("A")
答案 1 :(得分:8)
答案 2 :(得分:4)
改进@ miensol的解决方法并使其在视觉上与函数调用相同:
val <T> T.foo: (T) -> SomeType get() = { other -> ... }
这是一个提供lambda的扩展属性,可以使用相同类型T
的参数立即调用,如下所示:
"abc".foo(1) // Fail
"abc".foo("def") // OK
不幸的是, seems to be a bug in the compiler 会阻止您撰写"abc".thing("abc")
,但"abc".thing.invoke("abc")
和("abc".thing)("abc)
都可以正常运行并过滤掉非字符串。