Ответ 1
Я нашел способ сделать это в Kotlin 1.0, используя Nothing
из stdlib:
/* requires passing all arguments by name */
fun f0(vararg nothings: Nothing, arg0: Int, arg1: Int, arg2: Int) {}
f0(arg0 = 0, arg1 = 1, arg2 = 2) // compiles with named arguments
//f0(0, 1, 2) // doesn't compile without each required named argument
/* requires passing some arguments by name */
fun f1(arg0: Int, vararg nothings: Nothing, arg1: Int, arg2: Int) {}
f1(arg0 = 0, arg1 = 1, arg2 = 2) // compiles with named arguments
f1(0, arg1 = 1, arg2 = 2) // compiles without optional named argument
//f1(0, 1, arg2 = 2) // doesn't compile without each required named argument
Поскольку Array<Nothing>
является незаконным в Kotlin, значение для vararg nothings: Nothing
не может быть создано для передачи в (если не считать отражения). Это кажется немного взломанным, хотя и я подозреваю, что в байтоде есть некоторые накладные расходы для пустого массива типа Nothing
, но он, похоже, работает.
Этот подход не работает для первичных конструкторов класса данных, которые не могут использовать vararg
, но они могут быть помечены как private
, а вторичные конструкторы могут использоваться с vararg nothings: Nothing
.
Этот подход, однако, не работает в Kotlin 1.1: "Запрещенный тип параметра vararg: Nothing".:-(
К счастью, в Котлине нет надежды. Вы можете реплицировать этот шаблон, указав свой собственный пустой класс с помощью частного конструктора (например, Nothing
) и используя это как первый параметр varargs. Конечно, это не должно было быть сделано, если форсированные именованные аргументы были официально поддержаны.