使用Java中的类委派调用Kotlin对象作为静态方法

jvi*_*cek 17 java delegates kotlin kotlin-interop

这可能有点难以描述,因此我将尝试给出我正在尝试做的具体示例.

假设我们有一个Facade接口和类(在Java中),如下所示:

interface FacadeInterface<T> {
    void method(String from, String via);
}

class Facade<T> implements FacadeInterface<T> {
    private Class<T> mClazz;

    public Facade(Class<T> clazz) {
        mClazz = clazz;
    }

    @Override
    public void method(String from, String via) {
        System.out.println("Method called from " + from + " via " + via);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,我需要有多个单例来保存外观的实例.真正的外观有额外的设置/配置参数,但这些与此无关.

在我开始使用kotlin之前,我会有一个类,它包含一个静态的外观实例(不是真正的单例,但在我的情况下,它起到了类似的作用)代理了对外观的调用,如下所示:

public class Singleton {
    private static final FacadeInterface<String> sFacade = new Facade<>(String.class);

    private Singleton() {
    }

    public static void method(String from, String via) {
        sFacade.method(from, via);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,有了Kotlin,我们有类代表,允许我写这样的东西:

object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
Run Code Online (Sandbox Code Playgroud)

这很棒 - 没有更多的样板,我可以像调用java一样SingletonKt 从Kotlin类调用Singleton:

Singleton.method("Kotlin", "Singleton")
SingletonKt.method("Kotlin", "SingletonKt")
Run Code Online (Sandbox Code Playgroud)

但是,当我使用SingletonKt Java时会出现一个小问题.然后我必须指定INSTANCE:

Singleton.method("Java", "Singleton");
SingletonKt.INSTANCE.method("Java", "SingletonKt");
Run Code Online (Sandbox Code Playgroud)

我知道@JvmStatic注释,但是我可以将它放在SingletonKt文件中而不会导致编译错误的唯一地方就在此之前FacadeInterface它似乎没有做到这一点.

有没有办法设置这个类委托,以便我可以从Java中调用它,就好像它是一个静态方法,而不引入创建代理方法的样板SingletonKt(这会破坏类委托的目的)?

tyn*_*ynn 6

可惜是不可能的!

科特林代表团是减少样板代码的好方法。但随之而来的是无法实际访问类体内的委托。

您面临的第二个问题@JvmStatic实际上比第一个更严重,并且在手动实施委派时也适用于您:

覆盖成员不能是对象中的“@JvmStatic”

因此,您可以将其委托给对象上的a,而不是method()通过INSTANCE唯一公开staticMethod()。这仍然与您的意图不同,但接近它。

object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
    @JvmStatic fun staticMethod(from: String, via: String) = method(from, to)
}
Run Code Online (Sandbox Code Playgroud)