首页 > 解决方案 > 我可以将 Kotlin 调用者的方法标记为已弃用,但 Java 调用者不可以吗?

问题描述

我想以一种对 Kotlin 调用者有用但对 Java 调用者有用的方式扩展 API。因此,我想鼓励 Kotlin 用户切换到新方法,而不会打扰 Java 用户。我们有一个混合了 Java 和 Kotlin 的大型代码库,而且短期内不会是 100% Kotlin。

有没有办法添加@Deprecate只出现在 Kotlin 而不是 Java 中的标签或类似标签?

如果您对具体细节感兴趣,我们有一个Log接受格式化字​​符串的接口,如下所示:

Log.get().info("Log message with some $expensive $things to $format")

即使禁用了日志记录,也会在每次调用时创建该字符串。修复记录器 API 以分别获取格式字符串和参数将是一个重大且具有破坏性的更改。然而,Kotlin 的可空类型可以给我们一个非常便宜的解决方案:

Log.getNullable()?.info("This $expensive $format should be skipped if there's no logger")

只是在所有 Kotlin 代码中get().替换为的情况。getNullable()?.但我不想getNullable()在 Java 代码中使用,因为存在NullPointerException. 因此,理想情况下,旧Log.get方法应该在 Kotlin 中被弃用,而不是在 Java 中。

标签: javakotlin

解决方案


假设一个类Log的方法在 中定义companion object,例如:

class Log {
  companion object {
    @JvmStatic
    fun get() : String = TODO()
    @JvmStatic
    fun getNullable() : String? = TODO()
  }
}

只是删除@JvmStatic? 还是创建一个扩展功能?

fun Log.Companion.getNullable() : String? = TODO()
class Log {
  companion object {
    @JvmStatic
    fun get() : String = TODO()
  }
}

扩展函数在 Java 中通常不像在 Kotlin 中那样容易访问。在 Java 代码中,删除@JvmStatic或扩展函数都需要以下内容:Log.Companion.getNullable而不是Log.getNullable... 也许这对您来说也可以,而不是弃用它。

即使我的猜测是错误的,扩展功能也可能满足您的需求。

关于仅弃用 Kotlin 的方法...我认为这不起作用,但这是另一种解决方法。只需重命名方法并@JvmName("get")在方法上使用,例如:

@JvmStatic
@JvmName("get")
fun dont_ever_use_this_method_again_in_Kotlin() : String = TODO()

这将允许Log.get来自 Java,但不允许来自 Kotlin。而且我认为我们可以同意没有人会调用Log.dont_ever_use_this_method_again_in_KotlinKotlin,对吧?


推荐阅读