2016-05-23 2 views
12

У меня есть некоторые конструкторы и функции, которые я бы всегда вызывал с именованными аргументами. Есть ли способ потребовать этого?Как заставить вызовы некоторым конструкторам/функциям использовать именованные аргументы?

Я хотел бы быть в состоянии сделать это для конструкторов и функций со многими параметрами и для тех, которые читают более ясно, когда используются именованные аргументы, и т.д.

+1

Релевантная ошибка Kotlin: https://youtrack.jetbrains.com/issue/KT-14934 –

ответ

13

Я нашел способ сделать это в Котлин 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> является незаконным в Котлин, значение для vararg nothings: Nothing не может быть создан, чтобы быть переданы в (короткое отражения я полагаю). Это кажется немного взломанным, хотя и я подозреваю, что в байтоде есть некоторые накладные расходы для пустого массива типа Nothing, но он работает.

Этот подход не работает для первичных конструкторов класса данных, которые не могут использовать vararg, но они могут быть помечены как private, а вторичные конструкторы могут использоваться с vararg nothings: Nothing.

Этот подход, однако, не работает в Kotlin 1.1: «Запретный параметр параметра vararg: Nothing». :-(

К счастью, в Kotlin 1.1 не теряется надежда. Вы можете реплицировать этот шаблон, указав свой собственный пустой класс с помощью частного конструктора (например, Nothing) и используя его в качестве первого параметра varargs. Конечно, это не нужно было бы делать, если бы форсированные именованные аргументы были официально поддержаны.

+14

Хотя это никогда не предназначалось для дизайна языка , Я приветствую вашу изобретательность :) –

+0

Вы можете распространять массив Nothing с * arrayOf (). Или вы должны уметь, я думаю, – Deanveloper

+0

@Deanveloper Я только что попробовал. Я получаю: «Unsuppored [Array в обратном типе является незаконным» и «Не может использовать« Nothing »в качестве параметра типа reified». Даже если бы вы могли, последующие аргументы в, например, 'f0 (* arrayOf (), 0, 1, 2)' объединены с содержимым массива с расширением, что вызывает другую ошибку: «Целый литерал не соответствовать ожидаемому типу «ничего». – mfulton26

Смежные вопросы