Есть ли способ смягчить эту проблему...
Вроде как, но это не готовое решение. Подробнее об этом ниже.
... это цена, которую я должен заплатить за смешивание Java и Kotlin?
Нет. Если мы обратимся к этой проблеме, вы заметите, что именно Java не может предоставлять значения по умолчанию и, следовательно, неудобна при использовании с Kotlin. Строительство сложных объектов является основной причиной, по которой Шаблон построителя существует. Но Kotlin дает нам решение, позволяющее избежать большинства проблем, связанных с созданием сложных объектов, и делает шаблон построителя устаревшим.
Как с этим бороться?
Существует не одно решение, а несколько. Назову как минимум два, которые пришли мне в голову сразу:
- Первичный + вторичный конструктор;
- Заводы.
Первичный + вторичный конструктор
С помощью этой опции вы можете создать первичный конструктор со всем списком параметров, которые должен содержать ваш класс, и ввести вторичный конструктор, который принимает только те значения, которые требуются или не могут быть установлены по умолчанию:
class Example(val param1: Any, val param2: Any? = null, val param3: Any? = null) {
// In this situation we have to use different argument names
// to make explicit use of primary constructor.
// e.g. if we remove `param1 = ` or rename `requiredParam` to `param1`
// we will get an error saying: "There's a cycle in the delegation calls chain"
constructor(requiredParam: Any) : this(param1 = requiredParam)
}
Заводы
В случае с фабриками все выглядит почти так же. Хотя это решение будет более подробным в Java, но оно устраняет необходимость использования именованных аргументов и дает нам свободу для дополнительной подготовки перед инициализация объекта. Мы даже можем сделать его асинхронным (как если бы это был сетевой вызов)!
class Example(val param1: Any, val param2: Any? = null, val param3: Any? = null) {
object Factory {
fun from(param1: Any): Example {
return Example(param1)
}
}
}
Вывод
Нет правильного решения. Мы можем выбрать тот, который нам нравится, или, может быть, придумать новый.
- Primary + secondary constructor:
- (+) less verbose when used from Java;
- (-) при изменении вторичного конструктора вам придется обновить код Java;
- (-) требует разных имен для аргументов конструктора.
- Factories:
- (+) gives more freedom: e.g. you can calculate something within
from
function and it will be more readable in comparison to constructors;
- (+) скрывает реализацию конструктора. Позже вы сможете изменить конструкторы без изменения кода Java или фабричных функций;
- (-) будет более подробным при использовании из Java.
person
Jenea Vranceanu
schedule
21.08.2020
@JvmOverloads
для создания всех перегруженных конструкторов с параметрами по умолчанию, применяемыми при использовании класса из Java. Но вы не хотите использовать это для чего-то с 15 параметрами, у которых есть значения по умолчанию, потому что тогда вы смотрите на 2 ^ 15 конструкторов. Не уверен, что еще можно сделать. - person Tenfour04   schedule 21.08.20202^15 constructors
определенно стоит подумать, сомневаюсь, что кто-то будет это делать на самом деле (зная стоимость). - person Jenea Vranceanu   schedule 21.08.2020