Классы в Kotlin

Классы в Kotlin объявляются с помощью ключевого слова class:

class Invoice { /*...*/ }

Объявление класса состоит из имени класса, заголовка класса (с указанием его параметров типа, основного конструктора и т. д.) и тела класса, заключенного в фигурные скобки. И заголовок, и тело не являются обязательными; если у класса нет тела, фигурные скобки можно опустить.

class Empty

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

Класс в Kotlin может иметь первичный конструктор и один или несколько вторичных конструкторов. Основной конструктор является частью заголовка класса: он идет после имени класса (и дополнительных параметров типа).

class Person constructor(firstName: String) { /*...*/ }

Если у основного конструктора нет аннотаций или модификаторов видимости, ключевое слово constructor можно опустить:

class Person(firstName: String) { /*...*/ }

Основной конструктор не может содержать никакого кода. Код инициализации может быть помещен в блоки инициализатора, которые имеют префикс с ключевым словом init.

Во время инициализации экземпляра блоки инициализатора выполняются в том же порядке, в каком они появляются в теле класса, чередующиеся с инициализаторами свойств:

class InitOrderDemo(name: String) {
    val firstProperty = "First property: $name".also(::println)
    
    init {
        println("First initializer block that prints ${name}")
    }
    
    val secondProperty = "Second property: ${name.length}".also(::println)
    
    init {
        println("Second initializer block that prints ${name.length}")
    }
}

Вывод:

First property: hello
First initializer block that prints hello
Second property: 5
Second initializer block that prints 5

Обратите внимание, что параметры первичного конструктора могут использоваться в блоках инициализатора. Их также можно использовать в инициализаторах свойств, объявленных в теле класса:

class Customer(name: String) {
    val customerKey = name.toUpperCase()
}

Фактически, для объявления свойств и их инициализации из основного конструктора Kotlin имеет краткий синтаксис:

class Person(val firstName: String, val lastName: String, var age: Int) { /*...*/ }

Вы можете использовать конечную запятую при объявлении свойств класса:

class Person(
    val firstName: String,
    val lastName: String,
    var age: Int, // конечная запятая
) { /*...*/ }

Во многом так же, как и обычные свойства, свойства, объявленные в основном конструкторе, могут быть изменяемыми (var) или доступными только для чтения (val).

Если у конструктора есть аннотации или модификаторы видимости, необходимо ключевое слово constructor, а перед ним идут модификаторы:

class Customer public @Inject constructor(name: String) { /*...*/ }

Вторичные конструкторы

Класс также может объявлять вторичные конструкторы с префиксом constructor:

class Person {
    var children: MutableList<Person> = mutableListOf()
    constructor(parent: Person) {
        parent.children.add(this)
    }
}

Если у класса есть первичный конструктор, каждый вторичный конструктор должен делегировать основному конструктору, прямо или косвенно, через другой вторичный конструктор(ы). Делегирование другому конструктору того же класса выполняется с помощью ключевого слова this:

class Person(val name: String) {
    var children: MutableList<Person> = mutableListOf()
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}

Обратите внимание, что код в блоках инициализатора фактически становится частью основного конструктора. Делегирование первичному конструктору происходит как первая инструкция вторичного конструктора, поэтому код во всех блоках инициализатора и инициализаторах свойств выполняется перед телом вторичного конструктора. Даже если у класса нет основного конструктора, делегирование по-прежнему происходит неявно, и блоки инициализатора по-прежнему выполняются:

class Constructors {
    init {
        println("Init block")
    }
 
    constructor(i: Int) {
        println("Constructor")
    }
}

Вывод:

Init block
Constructor

Если неабстрактный класс не объявляет никаких конструкторов (первичных или вторичных), у него будет сгенерированный первичный конструктор без аргументов. Видимость конструктора будет общедоступной (public). Если вы не хотите, чтобы у вашего класса был общедоступный конструктор, вам необходимо объявить пустой первичный конструктор с видимостью, отличной от видимости по умолчанию:

class DontCreateMe private constructor () { /*...*/ }

Примечание. В JVM, если все параметры основного конструктора имеют значения по умолчанию, компилятор сгенерирует дополнительный конструктор без параметров, который будет использовать значения по умолчанию. Это упрощает использование Kotlin с такими библиотеками, как Jackson или JPA, которые создают экземпляры классов с помощью конструкторов без параметров.

class Customer(val customerName: String = "")

Создание экземпляров классов

Чтобы создать экземпляр класса, мы вызываем конструктор, как если бы это была обычная функция:

val invoice = Invoice()
 
val customer = Customer("Joe Smith")

Обратите внимание, что в Kotlin нет ключевого слова new.

Члены класса

Классы могут содержать:

  • Конструкторы и блоки инициализаторов
  • Функции
  • Свойства
  • Вложенные и внутренние классы
  • Объявления объекта

Читайте также:


Комментарии

Популярные сообщения из этого блога

Строки в Kotlin

Наследование в Kotlin

Возврат и прыжки в Kotlin