使用来自 Java 的 class 委托作为静态方法调用 Kotlin 对象
Call Kotlin object with class delegation from Java as a static method
这可能有点难以描述,所以我将尝试给出一个具体的例子来说明我正在尝试做的事情。
假设我们有一个 Facade 接口和 class(在 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);
}
}
在我的应用程序中,我需要有多个单例来保存外观的一个实例。真实的外观有额外的 setup/config 参数,但这些参数在这里无关紧要。
在我开始使用 kotlin 之前,我会有一个 class 来保存外观的静态实例(不是真正的单例,但在我的例子中,它起到了类似的作用),它代理了对立面,像这样:
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 中,我们有 class 个代表,它们允许我写这样的东西:
object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
这很棒 - 不再有样板文件,我可以从 Kotlin class 调用 SingletonKt
,就像我调用 java 一样Singleton
:
Singleton.method("Kotlin", "Singleton")
SingletonKt.method("Kotlin", "SingletonKt")
但是,当我从 Java 使用 SingletonKt
时出现了一个小问题。然后我必须指定 INSTANCE
:
Singleton.method("Java", "Singleton");
SingletonKt.INSTANCE.method("Java", "SingletonKt");
我知道 @JvmStatic
注释,但我可以将它放在 SingletonKt
文件中而不会导致编译错误的唯一位置是在 FacadeInterface
之前,但它不会似乎可以解决问题。
有没有办法设置这个 class 委托,这样我就可以从 Java 调用它,就好像它是一个静态方法一样,而无需引入为 [= 创建代理方法的样板17=](这会破坏 class 代表的目的)?
我不知道在 Kotlin 中是否可以将委托方法作为对象内部的静态方法。
但是,由于您有兴趣创建代理 class 的单例,您可以在 Kotlin 中使用包级常量:
val SingletonKt : FacadeInterface<String> = Facade(String::class.java)
现在,您可以像在 Java 中一样调用 SingletonKt.method
。请注意,您需要在 Java 中使用静态导入才能使用 SingletonKt
常量。
这还允许您使用 lazy
等功能仅在需要时创建单例(或在本例中为实例)。
遗憾的是这不可能!
Kotlin Delegation 是减少样板代码的好方法。但它伴随着无法实际访问 class 体内的委托。
您面临的关于 @JvmStatic
的第二个问题实际上比第一个问题更严重,并且在手动实施委派时也适用于您:
Override members cannot be '@JvmStatic' in object
因此,您可以将其委托给对象上的 staticMethod()
,而不是仅通过 INSTANCE
公开 method()
。这仍然与您的意图不同,但接近它。
object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
@JvmStatic fun staticMethod(from: String, via: String) = method(from, to)
}
这可能有点难以描述,所以我将尝试给出一个具体的例子来说明我正在尝试做的事情。
假设我们有一个 Facade 接口和 class(在 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);
}
}
在我的应用程序中,我需要有多个单例来保存外观的一个实例。真实的外观有额外的 setup/config 参数,但这些参数在这里无关紧要。
在我开始使用 kotlin 之前,我会有一个 class 来保存外观的静态实例(不是真正的单例,但在我的例子中,它起到了类似的作用),它代理了对立面,像这样:
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 中,我们有 class 个代表,它们允许我写这样的东西:
object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
这很棒 - 不再有样板文件,我可以从 Kotlin class 调用 SingletonKt
,就像我调用 java 一样Singleton
:
Singleton.method("Kotlin", "Singleton")
SingletonKt.method("Kotlin", "SingletonKt")
但是,当我从 Java 使用 SingletonKt
时出现了一个小问题。然后我必须指定 INSTANCE
:
Singleton.method("Java", "Singleton");
SingletonKt.INSTANCE.method("Java", "SingletonKt");
我知道 @JvmStatic
注释,但我可以将它放在 SingletonKt
文件中而不会导致编译错误的唯一位置是在 FacadeInterface
之前,但它不会似乎可以解决问题。
有没有办法设置这个 class 委托,这样我就可以从 Java 调用它,就好像它是一个静态方法一样,而无需引入为 [= 创建代理方法的样板17=](这会破坏 class 代表的目的)?
我不知道在 Kotlin 中是否可以将委托方法作为对象内部的静态方法。
但是,由于您有兴趣创建代理 class 的单例,您可以在 Kotlin 中使用包级常量:
val SingletonKt : FacadeInterface<String> = Facade(String::class.java)
现在,您可以像在 Java 中一样调用 SingletonKt.method
。请注意,您需要在 Java 中使用静态导入才能使用 SingletonKt
常量。
这还允许您使用 lazy
等功能仅在需要时创建单例(或在本例中为实例)。
遗憾的是这不可能!
Kotlin Delegation 是减少样板代码的好方法。但它伴随着无法实际访问 class 体内的委托。
您面临的关于 @JvmStatic
的第二个问题实际上比第一个问题更严重,并且在手动实施委派时也适用于您:
Override members cannot be '@JvmStatic' in object
因此,您可以将其委托给对象上的 staticMethod()
,而不是仅通过 INSTANCE
公开 method()
。这仍然与您的意图不同,但接近它。
object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
@JvmStatic fun staticMethod(from: String, via: String) = method(from, to)
}