Вызовите объект Kotlin с передачей класса из Java в качестве статического метода
Это может быть трудно описать, поэтому я попытаюсь привести конкретный пример того, что я пытаюсь сделать.
Предположим, что у нас есть интерфейс и класс 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)
Это здорово - не больше шаблонов, и я могу назвать SingletonKt
из классов Kotlin так же, как я назвал java Singleton
:
Singleton.method("Kotlin", "Singleton")
SingletonKt.method("Kotlin", "SingletonKt")
Но возникает небольшая проблема, когда я использую SingletonKt
из Java. Затем я должен указать INSTANCE
:
Singleton.method("Java", "Singleton");
SingletonKt.INSTANCE.method("Java", "SingletonKt");
Я знаю аннотацию @JvmStatic
, но единственное место, где я могу помещать его в файл SingletonKt
не вызывая ошибок компиляции, находится прямо перед FacadeInterface
и похоже, что это не трюк.
Есть ли способ настроить делегат этого класса, чтобы я мог его вызывать из Java, как если бы это был статический метод, без введения шаблона создания прокси-методов для SingletonKt
(что бы победить цель делегата класса)?
Ответы
Ответ 1
Это, к сожалению, не возможно!
Делегирование Kotlin - прекрасный способ уменьшить шаблонный код. Но это связано с невозможностью фактически получить доступ к делегату внутри тела класса.
Вторая проблема, с которой вы сталкиваетесь в отношении @JvmStatic
на самом деле более радикальна по отношению к вашему делу, чем первая, а также применима к вам при реализации делегирования вручную:
Элементы переопределения не могут быть "@JvmStatic" в объекте
Поэтому вместо того, чтобы разоблачить method()
помощью INSTANCE
, вы можете делегировать его staticMethod()
для объекта. Это по-прежнему отличается от ваших намерений, но приближается к нему.
object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
@JvmStatic fun staticMethod(from: String, via: String) = method(from, to)
}
Ответ 2
Я не знаю, можно ли делегировать методы как статические методы внутри объекта в Котлине.
Однако, поскольку вы заинтересованы в создании синглонов, которые проксируют класс, вы можете использовать константы уровня пакета в Kotlin:
val SingletonKt : FacadeInterface<String> = Facade(String::class.java)
Теперь вы можете вызвать SingletonKt.method
же, как и на Java. Обратите внимание, что вам нужно использовать статический импорт в Java, чтобы использовать константу SingletonKt
.
Это также позволяет использовать такие функции, как lazy
только создавать синглтон (или, в данном случае, экземпляр), когда вам это нужно.