Kotlin Constructors
1. обзор
В этом уроке мы подробно рассмотрим конструкторы в Kotlin.
Давайте начнем с краткого обзора концепции: мы используем конструкторы для создания объектов. Они выглядят как объявления методов, но всегда имеют то же имя, что и класс, и ничего не возвращают.
Для настройки проекта Kotlin взгляните на нашintroductory tutorial.
В Kotlin класс может иметь первичный конструктор и один или несколько дополнительных вторичных конструкторов.
В следующих разделах мы рассмотрим каждый тип и связанные с ним концепции.
2. Первичный Конструктор
Первый способ создать объект в Kotlin - использовать первичный конструктор.
This is a part of the class header. Параметры также могут быть полями класса, которые мы помещаем после объявления класса.
Давайте посмотрим на объявление базового класса с двумя свойствами и основным конструктором:
class Person constructor(val name: String, val age: Int? = null)
В этом примере мы объявили свойства через skeywordval . Это ведет себя так же, как обычные переменные, с учетом того, что свойстваval доступны только для чтения (аналог skeywordfinal в Java).
Если мы хотим изменить ссылку позже, мы должны использовать вместо этого skeywordvar . Однако мы не можем опускать тип поля в основном конструкторе, так как он должен быть явным.
In some cases, we can omit the constructor keyword. Это обязательно только в двух случаях: когда мы используем аннотации, такие как@Autowired, или модификаторы доступа, такие какprivate илиprotected.
Также мы можем использовать параметры Kotlin по умолчанию в конструкторах.
Затем давайте посмотрим, как мы можем использовать наш основной конструктор:
val person = Person("John")
val personWithAge = Person("Mark", 22)
Мы видим, чтоa class name is a constructor invocation. There’s no need to use the new keyword.
Для справки, давайте также посмотрим на Java-эквивалент объявления конструктора:
class PersonJava {
final String name;
final Integer age;
public PersonJava(String name) {
this.name = name;
this.age = null;
}
public PersonJava(String name, Integer age) {
this.name = name;
this.age = age;
}
}
Как видите, для достижения того же результата Java потребуется гораздо больше кода.
2.1. Первичные Конструкторы на JVM
Обратите внимание, что компилятор сгенерирует дополнительный конструктор без параметров в JVM. Для этого он создаст экземпляр объекта со значениями по умолчанию.
Таким образом, Kotlin может хорошо работать с такими библиотеками, как Jackson или JPA, которые используют конструктор no-args для создания экземпляров классов:
class Person(val name: String = "")
3. Инициализация свойств из параметров конструктора
Инициализаторы свойств из тела класса могут использовать параметры основного конструктора.
Преобразуемname в свойствоupperCaseName:
class Person(val name: String, val age: Int? = null) {
val upperCaseName: String = name.toUpperCase()
}
Мы можем увидеть вывод в консоли, добавив второй блокinit:
init {
println("Upper case name is $upperCaseName")
}
4. Блоки инициализатора
Мы не можем поместить какой-либо код в основной конструктор.
Однако нам иногда приходится выполнять некоторый код инициализации. Хорошее место для него - блок инициализатора, перед которым стоит ключевое словоinit.
The initializer block is called after the primary constructor. В этом месте мы также можем получить доступ к полям классов.
Класс может иметь один или несколько блоковinit.
Давайте добавим блок инициализатора в наш классPerson:
init {
println("Hello, I'm $name")
if (surname.isEmpty()) {
throw IllegalArgumentException("Surname cannot be empty!")
}
}
Затем, когда мы создадим объект классаPerson, мы увидим в консоли:
Hello, I'm John
Мы бы выбросилиIllegalArgumentException для пустогоsurname.
Когда у нас многоinit blocks, они будут выполняться в том же порядке, что и в теле класса.
5. Вторичный конструктор
В классе Kotlin мы также можем объявить один или несколько вторичных конструкторов.Secondary constructors are prefixed with the constructor keyword:
class Car {
val id: String
val type: String
constructor(id: String, type: String) {
this.id = id
this.type = type
}
}
И основное использование:
fun main(args: Array) {
val car = Car("1", "sport")
val suvCar = Car("2", "suvCar")
}
Each secondary constructor has to delegate to the primary constructor. Мы сделаем это с помощьюthis keyword.
Давайте переместим наши свойства вprimary constructor и изменимsecondary constructor:
class Car(val id: String, val type: String) {
constructor(id: String): this(id, "unknown")
}
6. Конструкторы и Наследование
Мы можем использовать первичный конструктор суперкласса.
Обратите внимание, что все классы в Kotlin по умолчанию имеютfinal . Это означает, что нам нужно добавить skeywordopen , чтобы мы могли наследовать от нашего классаPerson.
Давайте добавим классEmployee, который наследуется от классаPerson . Они оба используют первичные конструкторы:
class Employee(name: String, val salary: Int): Person(name)
Делая это, мы передаемname to основному конструктору классаPerson . Кроме того, мы добавляем новое поле с именемsalary в классEmployee.
7. Заключение
В этой быстрой статье мы обсудили различные способы создания конструкторов на языке Kotlin. Мы можем создавать наши поля различными способами, в соответствии с нашими пожеланиями.
Реализацию всех наших примеров можно найти вthe Github project.
Для получения дополнительной информации о функциях Kotlin, пожалуйста, посетите нашintroduction to Kotlin.