java - 对 Java 和 Kotlin 友好的 Kotlin 监听器

标签 java kotlin interop

我看过类似的问答,但没有找到我要找的东西 - 也许我遗漏了什么。

我想(在 Kotlin 类中)实现一个监听器属性。监听器只有一种方法,因此它是 lambda 友好的。

    interface Listener {
        fun onDone(id: String)
    }

...

    class Manager {
        var listener: Listener? = null
    }

当我想从 Java (8) 代码设置这个属性时,我可以使用 lambda 干净地完成它:

    manager.setListener(id -> {

    });

但是,在 Kotlin 中,我必须使用方法创建一个匿名对象:

    manager.listener = object : OfflineManager.Listener {
        override fun onDone(id: String) {
        }
    }

另一种选择,在 Kotlin 中使用函数引用:

var listener: ((String) -> Unit)? = null

在 Kotlin 中允许 nice lambda,但 Java lambda 需要一个返回值(即使该函数被定义为返回 Unit),这对 Java 开发人员来说很奇怪。

那么我怎样才能兼顾两者呢?

最佳答案

我相信没有直接的方法可以定义在 Java 和 Kotlin 中都“完全适用”的监听器。如果你想在 Java 中使用你的监听器,你必须坚持一个接口(interface),而 Kotlin 不支持 Kotlin 接口(interface)上的 SAM 转换:

[...] this feature [SAM conversions] works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.

然而,您可以创建一个扩展方法(这样它就不会在 Java 中作为 Manager 的方法之一可见)将给定的 lambda 转换为匿名对象:

inline fun Manager.setListener(crossinline onDone: (String) -> Unit) {
    listener = object : Listener {
        override fun onDone(id: String) {
            onDone(id)
        }
    }
}

通过这种方式,您可以在 Java 和 Kotlin 中保持它非常干净。


编辑: 上述的变体:

class Manager {
    private var listener: Listener? = null

    fun getListener(): Listener? = listener

    fun setListener(listener: Listener?) {
        this.listener = listener
    }
}

var Manager.onDone: (String) -> Unit
    get() = getListener()?.let { it::onDone } ?: {}
    set(value) {
        setListener(
            object : Manager.Listener {
                override fun onDone(id: String) {
                    value(id)
                }
            }
        )
    }

在这种情况下,在 Java 中,您仍然可以使用 setter 和 getter(必须显式编写)来引用监听器,并且基于 lambda 的字段在 Java 的 Manager 实例中不可见。在 Kotlin 中,listener 变量在 Manager 类之外是不可见的,它可以用作 lambda 字段。

然而,getListenersetListener 方法在 Kotlin 中都是可见和可访问的。此外,Kotlin 的 lambda 在转换为匿名对象时不会被内联。

关于java - 对 Java 和 Kotlin 友好的 Kotlin 监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57271884/

相关文章:

java - 持久性管理器中的 HashMap

java - Java中的接口(interface)方法重载

android - lateinit 的 isInitialized 属性在伴随对象中不起作用

kotlin - 必须在使用前声明 Kotlin 本地函数

android - 如何在 Sceneform Android SDK 中将相机类型更改为正交?

c# - 从 C++ 控制台应用程序调用的 C++ DLL 正常,从 C# 控制台应用程序调用有堆栈溢出

c++ - 如何在 OSX 上使用 glfw3 在 OpenGL 和 OpenCL 之间创建共享上下文?

c# - 如何让 C# 与 Javascript 互操作?

Java:简单的设置,但无法解析 "ClassNotFoundException: org.postgresql.Driver"

java - 投影后进行组聚合时引用无效