Простые примеры для демонстрации первичных и вторичных / множественных конструкторов в Kotlin
Эта статья была первоначально опубликована на vtsen.hashnode.dev 23 июля 2022 года.
В Kotlin у вас есть один первичный и множество вторичных конструкторов.
Первичный конструктор
Это первичный конструктор с одним параметром.
class Example constructor(private val param1: String) {
init {
println("init is called.")
}
}
Вы также можете опустить ключевое слово constructor
.
class Example(private val param1: String) {
init {
println("init is called.")
}
}
Вы НЕ можете инициализировать в первичном конструкторе. Вместо этого необходимо инициализировать код в блоке init{}
.
Вторичный конструктор
Ниже приведены 2 вторичных конструктора.
class Example(private val param1: String) {
init {
println("init is called.")
}
//First secondary constructor
constructor(
param1: String,
param2: String) : this(param1) {
println("Second constructor is called")
}
//Second secondary constructor
constructor(
param1: String,
param2: String,
param3: String) : this(param1) {
println("Third constructor is called")
}
}
Здесь есть несколько важных замечаний:
- Вы должны вызвать первичный конструктор (например, вызвать
this(param1)
). Не совсем так! Смотрите следующий раздел — Вызов другого вторичного конструктора - Вы можете объявить
var
илиval
в параметре вторичного конструктора - Вы можете инициализировать свой код во вторичном конструкторе
Обратите внимание, что первичный конструктор вместе с блоком init{}
вызывается первым перед инициализацией вторичного конструктора.
Поэтому, если я вызову третий конструктор,
val obj = Example(param1="1", param2="2", param3="3")
вывод будет выглядеть следующим образом.
init is called.
Third constructor is called
Вызов другого вторичного конструктора
Вместо вызова первичного конструктора во вторичном конструкторе можно также вызвать другой вторичный конструктор.
В этом примере второй вторичный конструктор вызывает первый вторичный конструктор.
class Example(private val param1: String) {
init {
println("init is called.")
}
//First secondary constructor
constructor(
param1: String,
param2: String) : this(param1) {
println("Second constructor is called")
}
//Second secondary constructor
constructor(
param1: String,
param2: String,
param3: String) : this(param1, param2) {
println("Third constructor is called")
}
}
Если я вызову третий конструктор, вывод будет выглядеть следующим образом:
init is called.
Second constructor is called
Third constructor is called
Пустой первичный конструктор
Это пример пустого первичного конструктора и вторичного конструктора.
class Example() {
init {
println("init is called.")
}
constructor(param1: String): this() {
println("Second constructor is called")
}
}
Однако на самом деле вам не нужно вызывать this()
в вашем вторичном конструкторе. Вам также нужно изменить Example()
на Example
.
class Example {
init {
println("init is called.")
}
constructor(param1: String) {
println("Second constructor is called")
}
}
Случай использования вторичного конструктора
Я столкнулся с необходимостью использования вторичного конструктора, когда хочу внедрить зависимость Hilt в мою модель представления.
%[https://vtsen.hashnode.dev/convert-view-model-to-use-hilt-dependency-injection]
У меня есть код вроде этого, где параметр preview
используется для @preview
jetpack compose. Он установлен в true
только в @preview
. Однако если я перенесу это изменение на использование инъекции зависимостей Hilt
, она не сможет инжектировать эту зависимость.
class MainViewModel(
private val repository: ArticlesRepository,
preview: Boolean = false,
) : ViewModel() {
/*...*/
}
Таким образом, я разбиваю это на вторичный конструктор ниже.
class MainViewModel(
private val repository: ArticlesRepository) : ViewModel() {
constructor (
repository: ArticlesRepository,
preview: Boolean) : this(repository) {
/*...*/
}
}
Поэтому я использую @Inject constructor
для первичного конструктора, а вторичный конструктор используется для @preview
.
С реализацией Hilt
это выглядит следующим образом
@HiltViewModel
class MainViewModel
@Inject constructor(
private val repository: ArticlesRepository,
) : ViewModel() {
constructor (
repository: ArticlesRepository,
preview: Boolean) : this(repository) {
/*...*/
}
/*...*/
}
Заключение
Я не часто использовал множественные конструкторы, а вы? Поэтому я задокументировал это здесь для будущего использования.
Смотрите также
- Советы и хитрости Kotlin