简体   繁体   English

更改kotlin扩展函数接收器JVM名称

[英]Changing kotlin extension function receiver JVM name

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 假设我有一个用kotlin编写的扩展函数,它将DP转换为PX并返回一个NonNull Int

fun Int.toPx() {  /** implementation */ }

The function in java will look something like this java中的函数看起来像这样

public int toPx(int $receiver) {  /** implementation */ }

In my opinion the $receiver makes the Java-interop feels generated and uninviting. 在我看来, $receiver使得Java-interop感觉生成和不受欢迎。

I know that you can use the @JvmName annotation with some combinations like @file:JvmName to change the name in java. 我知道您可以使用@JvmName注释和@file:JvmName类的组合来更改java中的名称。

When i'm trying to use @JvmName with the receiver site target it says 当我试图将@JvmNamereceiver站点目标一起使用@JvmName ,它说

"This annotation is not applicable to target type usage and use site target @receiver " “此注释不适用于目标type usage并使用站点目标@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. @JvmName只能应用于文件的函数,属性访问器和顶级包外观。 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. 但是,预计足够,这将无法编译,因为这两个函数将具有相同的JVM签名。 So, to disambiguate them, add @JvmName("...") to the extension and (optionally) mark the extension as inline : 因此,要消除它们的歧义,请将@JvmName("...")添加到扩展名,并(可选)将扩展名标记为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 . 要从Java隐藏扩展函数,您还可以使用@JvmSynthetic对其进行@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. 这个解决方案的缺点是顶层函数toPx泄漏到查看包的文件的IDE完成范围。

The parameter name is only relevant in Java regarding documentation (as a method signature hint in the IDE, when you call a method). 参数名称仅在Java中与文档相关(作为IDE中的方法签名提示,当您调用方法时)。 Unlike in Kotlin, it is never part of the calling code. 与Kotlin不同,它从不是调用代码的一部分。

If you define extension methods on existing types, I've found that a good approach is to name the file in a way that describes the receiver. 如果您在现有类型上定义扩展方法,我发现一个好方法是以描述接收器的方式命名文件。 While this doesn't matter for Kotlin (as extension methods will be called without the file name), it does for other JVM languages. 虽然这对Kotlin无关紧要(因为扩展方法将在没有文件名的情况下调用),但它适用于其他JVM语言。 Thus, the receiver type/meaning is not expressed by the parameter name, but by the class name. 因此,接收器类型/含义不是由参数名称表示,而是由类名表示。

You're already aware of @file:JvmName , so use it to your advantage: 你已经知道了@file:JvmName ,所以使用它有利于你:

@file:JvmName("Ints")

fun Int.toPx() { ... }

In Kotlin: 在Kotlin:

val value = 328
val px = value.toPx()

In Java, the code is very close to the Kotlin counterpart: 在Java中,代码非常接近Kotlin对应的代码:

int value = 328;
Pixel px = Ints.toPx(value);

Can of course be a longer name such as IntExtensions if that helps readability. 当然可以是更长的名称,如IntExtensions如果这有助于可读性。

Note that in Kotlin, it is explicitly allowed to reuse the same class name in @file:JvmName across multiple files, and the extensions functions will be combined in a single JVM class (see also here ). 请注意,在Kotlin中,明确允许在多个文件中的@file:JvmName重用相同的类名,并且扩展函数将组合在一个JVM类中(另请参见此处 )。 You need the annotation @file:JvmMultifileClass for this. 你需要注释@file:JvmMultifileClass

Thus, you could also have an Int extension completely unrelated to pixels in another file, yet it would still end up in the same Java class Ints . 因此,您还可以使Int扩展与另一个文件中的像素完全无关,但它仍然会在同一Java类Ints

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM