У меня есть фрагмент кода Котлина, где первый и второстепенный конструктор сильно отличаются, см. Ниже
class InstructionPrototype constructor( val iname: String, val opcode: Int, val mnemonicExample: String, val numericExample: Int, val description: String, val format: Format, val pattern: Pattern, var type: Type? = null, var rt: Int? = null, var funct: Int? = null, var conditions: Array<(n: Int) -> String?>? = null) { constructor( iname: String, opcode: Int, mnemonicExample: String, numericExample: Int, description: String, format: Format, pattern: Pattern, type: Type?, rt: Int?, funct: Int?, condition: (n: Int) -> String? ): this(iname, opcode, mnemonicExample, numericExample, description, format, pattern, type, rt, funct, arrayOf(condition)) { }
возможно ли уменьшить многословие этого через некоторую конструкцию языка? Я думал об алгебраических типах данных, но это не очень хорошо подходило – оно натолкнулось на «хаки».
Переменная количество аргументов ( vararg
), по- видимому, подходит для вашего vararg
использования очень хорошо, но только если вы можете отказаться от null
в качестве значения по умолчанию для conditions
поскольку vararg
не может быть нулевым (например, use emptyArray()
):
class InstructionPrototype constructor( val iname: String, val opcode: Int, val mnemonicExample: String, val numericExample: Int, val description: String, val format: Format, val pattern: Pattern, var type: Type? = null, var rt: Int? = null, var funct: Int? = null, vararg var conditions: (n: Int) -> String? = emptyArray())
На сайте использования вы можете передать одиночный (n: Int) -> String?
, и он будет упакован в массив и в дополнение к передаче нескольких функций, разделенных запятой, вы можете использовать оператор спредов для передачи массива:
f(vararg a: String) { } f("a") f("a", "b", "c") val array = arrayOf("a", "b", "c") f(*array) // any array of the correct type can be passed as vararg
Кроме того, несколько параметров до conditions
также имеют значения по умолчанию, и нет другого способа пропустить их и передать conditions
чем использовать именованные аргументы и оператор с расширением:
fun f(x: Int = 5, vararg s: String) { } f(5, "a", "b", "c") // correct f(s = "a") // correct f(s = "a", "b", "c") // error f(s = *arrayOf("a", "b", "c") // correct