簡體   English   中英

更改kotlin擴展函數接收器JVM名稱

[英]Changing kotlin extension function receiver JVM name

這是一個普遍的問題。 假設我有一個用kotlin編寫的擴展函數,它將DP轉換為PX並返回一個NonNull Int

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

java中的函數看起來像這樣

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

在我看來, $receiver使得Java-interop感覺生成和不受歡迎。

我知道您可以使用@JvmName注釋和@file:JvmName類的組合來更改java中的名稱。

當我試圖將@JvmNamereceiver站點目標一起使用@JvmName ,它說

“此注釋不適用於目標type usage並使用站點目標@receiver

有沒有辦法克服它並改變接收器的名稱,如果不是最好的選擇。

@JvmName只能應用於文件的函數,屬性訪問器和頂級包外觀。 不支持參數名稱。

基本上,您可以定義兩個函數,一個采用簡單參數,另一個采用接收器:

fun toPx(value: Int) { /* implementation */ }

fun Int.toPx() = toPx(this)

但是,預計足夠,這將無法編譯,因為這兩個函數將具有相同的JVM簽名。 因此,要消除它們的歧義,請將@JvmName("...")添加到擴展名,並(可選)將擴展名標記為inline

fun toPx(value: Int) { /* implementation */ }

@JvmName("toPxExtension") @Suppress("nothing_to_inline")
inline fun Int.toPx() = toPx(this)

要從Java隱藏擴展函數,您還可以使用@JvmSynthetic對其進行@JvmSynthetic

這個解決方案的缺點是頂層函數toPx泄漏到查看包的文件的IDE完成范圍。

參數名稱僅在Java中與文檔相關(作為IDE中的方法簽名提示,當您調用方法時)。 與Kotlin不同,它從不是調用代碼的一部分。

如果您在現有類型上定義擴展方法,我發現一個好方法是以描述接收器的方式命名文件。 雖然這對Kotlin無關緊要(因為擴展方法將在沒有文件名的情況下調用),但它適用於其他JVM語言。 因此,接收器類型/含義不是由參數名稱表示,而是由類名表示。

你已經知道了@file:JvmName ,所以使用它有利於你:

@file:JvmName("Ints")

fun Int.toPx() { ... }

在Kotlin:

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

在Java中,代碼非常接近Kotlin對應的代碼:

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

當然可以是更長的名稱,如IntExtensions如果這有助於可讀性。

請注意,在Kotlin中,明確允許在多個文件中的@file:JvmName重用相同的類名,並且擴展函數將組合在一個JVM類中(另請參見此處 )。 你需要注釋@file:JvmMultifileClass

因此,您還可以使Int擴展與另一個文件中的像素完全無關,但它仍然會在同一Java類Ints

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM