Первичный конструктор Kotlin вызывает вторичный конструктор
Почему это не компилируется?
class test
{
constructor() {
var a = Date().day
this(a)
}
constructor(a:Int) {
}
}
ошибка: выражение 'this' типа 'test' не может быть вызвано как функция. Функция invoke() не найдена.
Предлагаемое исправление состоит в том, чтобы добавить это:
private operator fun invoke(i: Int) {}
Зачем?
3 ответа
Во-первых, оба этих конструктора являются вторичными конструкторами. Первичный конструктор - это тот, который находится вне тела класса.
Во-вторых, как описано в документации, правильный синтаксис для вызова другого конструктора выглядит следующим образом:
class Test {
constructor() : this(1) { }
constructor(a: Int) { }
}
class test constructor(){ // primary constructor (The primary constructor is part of the class header: it goes after the class name (and optional type parameters))
constructor(a: Int) : this() { // secondary constructor
}
}
Если ваш класс должен определить primary constructor
, secondary constructor
необходимо делегировать primary constructor
, Смотрите здесь.
Я думаю primary constructor
нельзя звонить из secondary constructor
,
Вы можете думать так: вторичные звонки первичные и первичные звонки вторичные => бесконечный цикл => невозможно
В вашем случае есть 2 secondary constructor
так что вы можете сделать как
class test {
constructor() : this(Date().day) // I see it quite like Java here https://stackru.com/questions/1168345/why-do-this-and-super-have-to-be-the-first-statement-in-a-constructor
constructor(a: Int) {
}
}
Пара вещей здесь не так:
- Классы должны всегда использовать верблюжий кейс для своих имен (
test
->Test
) - Вы не можете вызвать другой конструктор, как вы пытались
this(1)
внутри тела других конструкторов)
Я думаю, что вы на самом деле хотите a
являясь свойством и, альтернативно, инициализировать его значением по умолчанию. Вы могли бы сделать это так
class Test(val a: Int) {
constructor() : this(1) // notice how you can omit an empty body
}
или даже лучше, вот так:
class Test(val a: Int = 1) // again an empty body can be omitted.
Редактировать:
Если вам нужно сделать некоторые расчеты, как указано в комментарии ниже, ответ Йоль:
class Test(val day: Int) {
// you can use any expression for initialization
constructor(millis: Long) : this(Date(millis).day)
}
или если все усложняется:
class Test(var day: Int) {
// pass something (i.e. 1) to the primary constructor and set it properly in the body
constructor(millis: Long) : this(1) {
// some code
day = // initialize day
}
}