3

我的 SDK 公开了一个只有静态方法的 Java 接口,例如

public interface MyDevice { 
  public static void setLocation(Location location) {…}
  public static Location getLocation() {…}
}

在使用 SDK 的 Java 应用程序中,我的客户可以像使用单例一样使用它们,例如

Location currentLocation = MyDevice.getLocation();

当这个 SDK 被集成到 Kotlin 应用程序中时,很自然地将其表达为属性:

val currentLocation = MyDevice.location

问题是,这个内置的互操作只适用于非静态方法。

我可以在 Kotlin 中创建一个单例并让它处理翻译:

object myDevice {
    var location: Location
    get() = MyDevice.getLocation()
    set(location) = MyDevice.setLocation(location)
}

但是,在其他纯 Java SDK 中的这个 Kotlin 文件不会对不使用 Kotlin 的客户产生负面影响吗?可以用Java表达吗?

或者我应该简单地将MyDevice.java转换为 Kotlin?对于仍在使用 Java 的客户,这样的步骤会有什么负面影响?

4

4 回答 4

2

您描述的问题是缺少元数据 Kotlin 需要将静态方法视为扩展函数的类扩展属性。

与问题KT-11968一起,至少目前无法实现。

最好的选择是将 API 转换为 Kotlin,并在必要时支持 @JvmStaic/@JvmField 和 @JvmDefault 以实现向后兼容性。

interface MyDevice {
  companion object {
    // nullable type or explicit init
    var location: Location? 
      @JvmStatic get
      @JvmStatic set


// kotlin
val x = MyDevice.location
MyDevice.location = x


// java
var x = MyDevice.getLocation();
MyDevice.setLocation(x);
于 2020-12-03T19:10:20.123 回答
1

在 Kotlin 中,为了实现与 Java 接口中的静态方法相同的结果,您应该使用 acompanion object来声明您的静态方法。例子:

interface MyDevice {

    // instance methods   

    companion object {
        // static methods

        @JvmStatic
        fun setLocation(location: Location) {...}

        @JvmStatic
        fun getLocation(): Location {...}
    }
}

注意@JvmStatic注释。当您从 Java 类调用这些 Kotlin 函数时,它们将被解释为静态方法。例子:

public void myJavaMethod() {
    Location location = MyDevice.getLocation();
}
于 2020-11-30T22:50:13.560 回答
1

kotlin lang 提供的解决方案很少,我们可以使用它来简化您的案例。kotlin 的本质是在 Java 之间更好地工作,对我来说,我没有看到使用 Companion/Object 创建类似于 Java 的静态方法的任何缺点。为了简单起见,kotlin 语言本身也为开发者提供了许多方便的助手。我们可以申请的内容如下:

  1. 目的
    object MyDevice {
    
        @JvmStatic
        fun getLocation(): Location {
        }
    
        @JvmStatic
        fun setLocation(location: Location) {
    
        }
    }
  1. 伴侣
    class MyDevice {
        companion object {
    
            @JvmStatic
            fun getLocation(): Location {
    
            }
    
            @JvmStatic
            fun setLocation(location: Location) {
    
            }
        }
    }

用Java调用:

MyDevice.setLocation(location);
final Location location = MyDevice.getLocation();
于 2020-12-10T08:51:27.033 回答
0

阅读了专家的回答,研究了他们提供的链接,并反编译了包装类的 Kotlin 代码并分析了一个使用 Kotlin 包装的库的演示应用程序(纯 Java),我决定更改 Java API。

现在我有一个带有公共静态对象的类:

public class MyDevice { 
  public static MyDevice myDevice;
  public void setLocation(Location location) {…}
  public Location getLocation() {…}
}

现在 Java 消费者将使用

import static com.example.sdk.MyDevice.myDevice;

Kotlin 消费者不需要那个static

import com.example.sdk.MyDevice.myDevice

所以,我的库不需要单独的 Kotlin 风格!

于 2020-12-31T14:19:41.397 回答