Когда я только начал писать 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”