использовать статические методы Java как статические (или одноэлементные) свойства в Kotlin
Мой SDK предоставляет интерфейс Java, в котором есть только статические методы, например
public interface MyDevice {
public static void setLocation(Location location) {…}
public static Location getLocation() {…}
}
В приложении Java, которое использует SDK, мои клиенты могут использовать их, как если бы это был синглтон, например
Location currentLocation = MyDevice.getLocation();
Когда этот SDK интегрирован в приложение Kotlin, было бы естественно выразить то же самое как свойство:
val currentLocation = MyDevice.location
Проблема в том, что это встроенное взаимодействие работает только с нестатическими методами.
Я могу создать синглтон в Kotlin и заставить его обрабатывать перевод:
object myDevice {
var location: Location
get() = MyDevice.getLocation()
set(location) = MyDevice.setLocation(location)
}
Но не повлияет ли этот единственный файл Kotlin в SDK, предназначенном только для Java, негативно на клиентов, которые не используют Kotlin? Можно ли то же самое выразить в Java?
Или, может быть, мне просто нужно преобразовать MyDevice.java в Kotlin? Каковы будут отрицательные последствия такого шага для клиентов, которые все еще используют Java?
4 ответа
Проблема, которую вы описали, заключается в отсутствии метаданных, которые Kotlin должен обрабатывать статические методы как свойства расширения класса функций расширения.
Вместе с выпуском КТ-11968 это делает невозможным, по крайней мере, пока.
Наилучшим вариантом является преобразование API в Kotlin с поддержкой @JvmStaic/@JvmField и @JvmDefault, где это необходимо для обратной совместимости.
В Kotlin для достижения того же результата, что и статические методы в интерфейсах Java, вы должны использовать
companion object
объявить ваши статические методы. Пример:
interface MyDevice {
// instance methods
companion object {
// static methods
@JvmStatic
fun setLocation(location: Location) {...}
@JvmStatic
fun getLocation(): Location {...}
}
}
Обратите внимание
@JvmStatic
аннотация. Когда вы вызываете эти функции Kotlin из класса Java, они будут интерпретироваться как статические методы. Пример:
public void myJavaMethod() {
Location location = MyDevice.getLocation();
}
Есть несколько решений, предоставляемых kotlin lang, мы можем использовать их, чтобы упростить ваш случай. Природа kotlin заключается в том, чтобы улучшить работу между Java, для меня я не видел никаких недостатков в использовании Companion/Object для создания статического метода, подобного Java. Сам язык kotlin также предоставляет множество удобных помощников для разработчика для простоты. Как показано ниже, что мы можем применить:
- Объект
object MyDevice {
@JvmStatic
fun getLocation(): Location {
}
@JvmStatic
fun setLocation(location: Location) {
}
}
- Компаньон
class MyDevice {
companion object {
@JvmStatic
fun getLocation(): Location {
}
@JvmStatic
fun setLocation(location: Location) {
}
}
}
Вызов в Java:
MyDevice.setLocation(location);
final Location location = MyDevice.getLocation();
Прочитав ответы экспертов, изучив предоставленные ими ссылки, декомпилировав код Kotlin класса-обертки и проанализировав демо-приложение (чистая Java), в котором использовалась Kotlin-обертка, я решил изменить Java API.
Теперь у меня есть класс с общедоступным статическим объектом:
public class MyDevice {
public static MyDevice myDevice;
public void setLocation(Location location) {…}
public Location getLocation() {…}
}
теперь потребители Java будут использовать
import static com.example.sdk.MyDevice.myDevice;
Потребителям Kotlin не нужен этот static :
import com.example.sdk.MyDevice.myDevice
Итак, мне не нужен отдельный вариант Kotlin для моей библиотеки!