Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

generics - How do I constrain a Kotlin extension function parameter to be the same as the extended type?

I want to write an extension method on a generic type T, where the matched type constrains a method parameter.

I want this to compile:

"Hello".thing("world")

But not this, as 42 is not a String:

"Hello".thing(42)

This definition doesn’t work, because T is satisfied by Any

fun <T> T.thing(p: T) {}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As mentioned by @Alexander Udalov it's not possible to do directly but there's a workaround where you define the extension method on another type like so:

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

With the above the following compiles:

"abc".ext.thing("A")

but the next fails

"abc".ext.thing(2)

with:

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)

As suggested by @hotkey it seems that it should be possible to avoid the need for explicit Wrapper type with the following extension property:

val <T> T.thing: (T) -> Any? get() = { println("extension body") }

And then use it as "abc".thing("A") but it also fails. Surprisingly the following does compile "abc".thing.invoke("A")


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...