从 Java 调用具有类委派的 Kotlin 对象作为静态方法

2022-09-02 10:52:35

这可能有点难以描述,所以我将尝试给出一个具体的例子来说明我想要做的事情。

假设我们有一个 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);
    }
}

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

在我开始使用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);
    }
}

现在,有了 Kotlin,我们有了类委托,它们允许我写这样的东西:

object SingletonKt : FacadeInterface<String> by Facade(String::class.java)

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

Singleton.method("Kotlin", "Singleton")
SingletonKt.method("Kotlin", "SingletonKt")

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

Singleton.method("Java", "Singleton");
SingletonKt.INSTANCE.method("Java", "SingletonKt");

我知道注释,但是我唯一可以将其放在文件中而不会引起编译错误的地方就在之前,它似乎不能解决问题。@JvmStaticSingletonKtFacadeInterface

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


答案 1

可悲的是,这是不可能的!

Kotlin 委托是减少样板代码的好方法。但它带来了无法在类体中实际访问委托的情况。

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

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

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

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

答案 2

我不知道是否有可能将委托方法作为 Kotlin 中对象中的静态方法。

但是,由于您对创建代理类的单例感兴趣,因此您可以在 Kotlin 中使用包级常量:

val SingletonKt : FacadeInterface<String> = Facade(String::class.java)

现在,您可以像在Java中一样调用。请注意,您需要在 Java 中使用静态导入才能使用常量。SingletonKt.methodSingletonKt

这也允许您在需要时使用诸如仅创建单例(或在本例中为实例)之类的功能。lazy


推荐