Котлин Конструкторы

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.