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

时间:2017-06-09 09:34:21

标签: 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);
    }
}

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

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

这很棒 - 不再需要样板,我可以像调用java SingletonKt一样从Kotlin 类调用Singleton

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

但是,当我使用Java中的SingletonKt 时会出现一些小问题。然后我必须指定INSTANCE

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

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

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

2 个答案:

答案 0 :(得分:3)

遗憾的是,这是不可能的!

Kotlin Delegation是减少样板代码的好方法。但它伴随着无法实际访问类体内的委托。

您对@JvmStatic所面临的第二个问题实际上比第一个问题更为激烈,并且在手动实施授权时也适用于您:

  

覆盖成员不能是&#39; @ JvmStatic&#39;在对象

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

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

答案 1 :(得分:1)

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

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

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

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

这也允许您使用lazy等功能,只在需要时创建单例(或者,在本例中为实例)。