Рубрики
Без рубрики

JvmOverloads – важная аннотация для взаимодействия Kotlin/Java

Обсуждается важность аннотации JvmOverloads для взаимодействия Kotlin / Java и почему это не сразу очевидно. С тегами android, kotlin, java.

Когда я только начал писать Kotlin, одним из моих любимых преимуществ были аргументы по умолчанию . Это способ для вас создать функцию (или конструктор), которая будет принимать значения по умолчанию для чего-либо. Таким образом, пользователь этого метода должен будет дать вам только то, что вам нужно. Однако эта возможность перегрузки функций значениями по умолчанию не пересекается с Java 1-1, и если вы собираетесь использовать оба языка в своем приложении, вам нужно обязательно включить аннотацию @JvmOverloads . В этом посте объясняется проблема взаимодействия и то, как эта аннотация решает ее.

Перегруженные Конструкторы В Java

Прежде чем показать, как они работают в Kotlin, вот как вы обычно пишете перегруженные конструкторы в Java:

public class Task {
    private String description;
    private Date date;
    private boolean isCompleted;

    public Task() {
        this("");
    }

    public Task(String description) {
        this(description, new Date());
    }

    public Task(String description, Date date) {
        this(description, date, false);
    }

    public Task(String description, Date date, boolean isCompleted) {
        this.description = description;
        this.date = date;
        this.isCompleted = isCompleted;
    }
}

Параметры По Умолчанию В Kotlin

Вот как класс будет определен в Kotlin, или так я думал:

// In Task.kt
data class Task(var description: String? = "", var date: Date? = Date(), var isCompleted: Boolean = false)

// In MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    // All of these statements are valid
    val task1 = Task()
    val task2 = Task("Test")
    val task3 = Task("Test", Date())
    val task4 = Task("Test", Date(), false)
}

Не потребуется много времени, чтобы понять, сколько времени и кода мы сэкономили, используя аргументы по умолчанию, не теряя при этом никакой гибкости. Или это сделали мы?

Проблема взаимодействия с Java

После написания вышеупомянутого класса Kotlin с аргументами по умолчанию я хотел использовать ту же идею в Java, но, к сожалению, это не сработало:

Task task1 = new Task(); // Valid - Java allows default constructor
Task task2 = new Task("Test"); // Compiler error - no constructor 
Task task3 = new Task("Test", new Date()); // Compiler error - no constructor
Task task4 = new Task("Test", new Date(), false); // Valid

Я сразу же пришел в замешательство. Это работало в Kotlin, но не в Java, и я знал, что существует 100%-ная взаимосвязь, поэтому я начал изучать разницу. Это было удивительно просто – Kotlin, имеющий собственный конструктор, может обрабатывать такие правила, как аргументы по умолчанию, как ему заблагорассудится – отдельно от Java. Однако, если мы действительно хотим полного взаимодействия с Java, нам необходимо создать все необходимые перегрузки.

JVM загружает аннотацию

К счастью, решение – это всего лишь простая аннотация. @ @Загрузка Javaoverload

data class Task @JvmOverloads constructor(var description: String? = "", var date: Date? = Date(), var isCompleted: Boolean = false)

Теперь, каждый раз, когда мы используем этот класс в Java, мы можем использовать любую перегруженную версию конструктора, которую сочтем необходимой, и все равно для определения объекта потребуется всего одна строка кода Kotlin.

Оригинал: “https://dev.to/adammc331/jvmoverloads—an-essential-annotation-for-kotlinjava-interrop”