This is a general question. Let's say I have an extension function written in kotlin which converts DP to PX and return a NonNull Int
fun Int.toPx() { /** implementation */ }
The function in java will look something like this
public int toPx(int $receiver) { /** implementation */ }
In my opinion the $receiver
makes the Java-interop feels generated and uninviting.
I know that you can use the @JvmName
annotation with some combinations like @file:JvmName
to change the name in java.
When i'm trying to use @JvmName
with the receiver
site target it says
"This annotation is not applicable to target type usage
and use site target @receiver
"
Is there a way to overcome that and change the name of the receiver and if not what is the best alternative.
@JvmName
can only be applied to functions, property accessors and top-level package facades for files. Parameter names are not supported.
Basically, you can define two functions, one taking a simple parameter and another one with receiver:
fun toPx(value: Int) { /* implementation */ }
fun Int.toPx() = toPx(this)
But, expectedly enough, this won't compile because the two functions would have the same JVM signatures. So, to disambiguate them, add @JvmName("...")
to the extension and (optionally) mark the extension as inline
:
fun toPx(value: Int) { /* implementation */ }
@JvmName("toPxExtension") @Suppress("nothing_to_inline")
inline fun Int.toPx() = toPx(this)
To hide the extension function from Java, you can also annotate it with @JvmSynthetic
.
The downside of this solution is the top-level function toPx
leaking into the IDE completion scope of the files that see the package.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With