Из документации :
Класс в Kotlin может иметь первичный конструктор и один или несколько вторичных конструкторов. Основной конструктор является частью заголовка класса: он идет после имени класса (и дополнительных параметров типа).
Это пример основного конструктора : class MyClass constructor()
Ключевое слово constructor
является обязательным, только если вы хотите указать модификатор видимости ( по умолчанию public
) и / или аннотацию, поэтому все следующие альтернативы эквивалентны:
class MyClass public constructor()
class MyClass constructor()
class MyClass()
class MyClass // parenthesis can be omitted if no argument is provided
Очевидно, что более краткая версия предпочтительнее более подробной, если вам нужен именно такой конструктор.
В дополнение к основным конструкторам вы также можете иметь ноль, один или несколько вторичные конструкторы . Вторичные конструкторы должны делегировать основному конструктору, прямо или косвенно - путем вызова другого вторичного конструктора - Пример: constructor(...) : this(...)
.
Если ваш класс не указывает ни один первичный конструктор, любой вторичный конструктор должен делегировать суперклассу. Пример: например, constructor(...) : super(...)
.
Если вы не укажете какой-либо первичный или вторичный конструктор, тогда ваш класс будет иметь неявный конструктор publi c по умолчанию, который не принимает аргументов (как в Java).
Итак, чтобы ответить на ваши вопросы:
Что означает constructor
на class MyClass constructor(): Fragment()
?
Он объявляет первичный конструктор, но, учитывая, что вы не указываете никаких модификаторов видимости или каких-либо аннотаций, его можно опустить. То же самое относится и к круглой скобке, поэтому его можно переписать как class MyClass : Fragment()
(обратите внимание, что бит : Fragment()
объявляет, что ваш класс расширяет Fragment
, и он указывает, что конструктор по умолчанию MyClass
должен вызывать пустой конструктор своего родителя (подробнее здесь )
Почему мне нужно было поставить this()
? Это обязательно для вторичных конструкторов, как описано выше.
Изменить
, как описано в моем комментарии ниже, в первом фрагменте кода вы:
- определяете вторичный конструктор (
constructor(parent: Activity)
) - не определяете первичный конструктор. Это потому, что у вас есть вторичный конструктор, но нет скобок после определения вашего класса (т.е.
class MyClass()
или class MyClass constructor()
- они эквивалентны, как описано выше), поэтому Kotlin не будет генерировать пустой первичный конструктор по умолчанию. для вас - ваш класс расширяется
Fragment
, и вы вызываете родительский конструктор как часть сигнатуры вашего класса. Для этого требуется первичный конструктор f или ваш класс должен быть там, как указано в ошибке, с которой вы столкнулись: Supertype initialization is impossible without primary constructor
.
Как решить проблему?
Один из возможных способов - это то, что вы сделали , т.е. определение как первичного, так и вторичного конструктора. Однако вы сможете создать экземпляр MyClass
двумя способами: с передачей родительской Activity или без нее. Это примерно эквивалентно следующему коду Java:
class MyClass extends Fragment {
private Activity parent;
public MyClass() {
super()
}
public MyClass(Activity parent) {
super()
this.parent = parent;
}
}
Вероятно, вы не хотите создавать этот класс без родительского Activity. В этом случае просто избавьтесь от вторичного конструктора - он вам не нужен - и создайте первичный конструктор, который принимает любой необходимый аргумент. Пример: class MyClass(val parent: Activity) : Fragment()
. Это очень краткий способ определить первичный конструктор, который принимает Activity на входе и назначает этот аргумент переменной экземпляра с именем parent
; val
означает, что parent
будет доступен только для чтения (т.е. Kotlin будет генерировать геттер, но не установщик), но если вам нужно, чтобы переменная экземпляра была изменяемой, вы можете использовать вместо этого var
(т.е. Kotlin будет генерировать как геттер, так и сеттер).
Это примерно эквивалентно следующему коду Java:
class MyClass extends Fragment {
private Activity parent;
public MyClass(Activity parent) {
this.parent = parent;
}
}