использовать статические методы 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 также предоставляет множество удобных помощников для разработчика для простоты. Как показано ниже, что мы можем применить:

  1. Объект
          object MyDevice {
    
        @JvmStatic
        fun getLocation(): Location {
        }
    
        @JvmStatic
        fun setLocation(location: Location) {
    
        }
    }
  1. Компаньон
          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 для моей библиотеки!

Другие вопросы по тегам