Spec-Zone.ru › Kotlin 2

Классы

Прежде чем создавать классы, подумайте, можно ли использовать класс данных, если его цель — хранить данные. Также можно расширить существующий класс с помощью расширения, а не создавать новый с нуля.

Как и другие объектно-ориентированные языки, Kotlin использует классы для инкапсуляции данных (свойств) и поведения (функций), создавая повторно используемый структурированный код.

Классы — это чертежи или шаблоны объектов, которые создаются с помощью конструкторов. Когда вы создаёте экземпляр класса, вы создаёте конкретный объект на основе этого шаблона.

В Kotlin предусмотрен лаконичный синтаксис для объявления классов. Чтобы объявить класс, используйте ключевое слово class, за которым следует имя класса:

class Person { /*...*/ }

Объявление класса состоит из следующих частей:

  • Заголовок класса, включающий, помимо прочего:

    • Ключевое слово class

    • Имя класса

    • Параметры типа (если есть)

    • Первичный конструктор (необязательно)

  • Тело класса (необязательно), заключённое в фигурные скобки {} и содержащее члены класса, например:

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

    • Блоки инициализации

    • Функции

    • Свойства

    • Вложенные и внутренние классы

    • Объявления объектов

Заголовок и тело класса могут быть минимальными. Если у класса нет тела, фигурные скобки {} можно опустить:

// Class with primary constructor, but without a body 
class Person(val name: String, var age: Int)

Ниже приведён пример объявления класса с заголовком и телом, а затем создания его экземпляра:

// Person class with a primary constructor 
// that initializes the name property
class Person(val name: String) {
    // Class body with age property
    var age: Int = 0
}

fun main() {
    // Creates an instance of the Person class by calling the constructor
    val person = Person("Alice")

    // Accesses the instance's properties
    println(person.name)
    // Alice
    println(person.age)
    // 0
}

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

Экземпляр создаётся, когда вы используете класс как шаблон для создания реального объекта, с которым будет работать ваша программа.

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

// Creates an instance of the Person class
val anonymousUser = Person()

В Kotlin можно создавать экземпляры:

  • Без аргументов (Person()): создаётся экземпляр со значениями по умолчанию, если они объявлены в классе.

  • С аргументами (Person(value)): создаётся экземпляр с указанными значениями.

Созданный экземпляр можно присвоить изменяемой (var) или доступной только для чтения (val) переменной:

// Creates an instance using the default value 
// and assigns it to a mutable variable
var anonymousUser = Person()

// Creates an instance by passing a specific value 
// and assigns it to a read-only variable
val namedUser = Person("Joe")

Экземпляры можно создавать там, где это необходимо: внутри функции main(), внутри других функций или внутри другого класса. Кроме того, экземпляры можно создавать внутри другой функции, а затем вызывать эту функцию из main().

Следующий код объявляет класс Person со свойством для хранения имени. В нём также показано, как создать экземпляр со значением по умолчанию конструктора и с указанным значением:

// Class header with a primary constructor 
// that initializes name with a default value
class Person(val name: String = "Sebastian")

fun main() {
    // Creates an instance using the default constructor's value
    val anonymousUser = Person()

    // Creates an instance by passing a specific value
    val namedUser = Person("Joe")

    // Accesses the instances' name property
    println(anonymousUser.name)
    // Sebastian
    println(namedUser.name)
    // Joe
}

В Kotlin, в отличие от других объектно-ориентированных языков программирования, при создании экземпляров классов не нужно использовать ключевое слово new.

Сведения о создании экземпляров вложенных, внутренних и анонимных внутренних классов см. в разделе Вложенные классы.

Конструкторы и блоки инициализации

При создании экземпляра класса вызывается один из его конструкторов. В Kotlin у класса может быть первичный конструктор и один или несколько вторичных конструкторов.

Первичный конструктор — это основной способ инициализации класса. Он объявляется в заголовке класса. Вторичный конструктор задаёт дополнительную логику инициализации и объявляется в теле класса.

Первичный и вторичные конструкторы необязательны, но у класса должен быть как минимум один конструктор.

Первичный конструктор

Первичный конструктор задаёт начальное состояние экземпляра при его создании.

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

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

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

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

Первичный конструктор может объявлять параметры как свойства. Используйте ключевое слово val перед именем аргумента, чтобы объявить свойство, доступное только для чтения, и ключевое слово var — для изменяемого свойства:

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

Эти свойства-параметры конструктора хранятся в экземпляре и доступны за пределами класса.

Можно также объявить параметры первичного конструктора, которые не являются свойствами. Перед такими параметрами не указываются val или var, поэтому они не сохраняются в экземпляре и доступны только внутри тела класса:

// Primary constructor parameter that is also a property
class PersonWithProperty(val name: String) {
    fun greet() {
        println("Hello, $name")
    }
}

// Primary constructor parameter only (not stored as a property)
class PersonWithAssignment(name: String) {
    // Must be assigned to a property to be usable later
    val displayName: String = name
    
    fun greet() {
        println("Hello, $displayName")
    }
}

К свойствам, объявленным в первичном конструкторе, могут обращаться функции-члены класса:

// Class with a primary constructor declaring properties
class Person(val name: String, var age: Int) {
    // Member function accessing class properties
    fun introduce(): String {
        return "Hi, I'm $name and I'm $age years old."
    }
}

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

class Person(val name: String = "John", var age: Int = 30) { /*...*/ }

Если при создании экземпляра конструктору не передано значение, для свойств используются значения по умолчанию:

// Class with a primary constructor 
// including default values for name and age
class Person(val name: String = "John", var age: Int = 30)

fun main() {
    // Creates an instance using default values
    val person = Person()
    println("Name: ${person.name}, Age: ${person.age}")
    // Name: John, Age: 30
}

Параметры первичного конструктора можно использовать для инициализации дополнительных свойств класса непосредственно в теле класса:

// Class with a primary constructor 
// including default values for name and age
class Person(
    val name: String = "John",
    var age: Int = 30
) {
    // Initializes the description property 
    // from the primary constructor parameters
    val description: String = "Name: $name, Age: $age"
}

fun main() {
    // Creates an instance of the Person class
    val person = Person()
    // Accesses the description property
    println(person.description)
    // Name: John, Age: 30
}

Как и в функциях, в объявлениях конструкторов можно использовать завершающие запятые:

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

Блоки инициализации

Первичный конструктор инициализирует класс и задаёт его свойства. В большинстве случаев для этого достаточно простого кода.

Если при создании экземпляра нужно выполнить более сложные операции, поместите эту логику в блоки инициализации внутри тела класса. Эти блоки выполняются при вызове первичного конструктора.

Объявите блоки инициализации с помощью ключевого слова init, за которым следуют фигурные скобки {}. Внутри фигурных скобок укажите код, который должен выполняться при инициализации:

// Class with a primary constructor that initializes name and age
class Person(val name: String, var age: Int) {
    init {
        // Initializer block runs when an instance is created
        println("Person created: $name, age $age.")
    }
}

fun main() {
    // Creates an instance of the Person class
    Person("John", 30)
    // Person created: John, age 30.
}

Добавьте столько блоков инициализации (init {}), сколько необходимо. Они выполняются в том порядке, в котором указаны в теле класса, вместе с инициализаторами свойств:

//sampleStart
// Class with a primary constructor that initializes name and age
class Person(val name: String, var age: Int) {
    // First initializer block
    init {
        // Runs first when an instance is created
        println("Person created: $name, age $age.")
    }

    // Second initializer block
    init {
        // Runs after the first initializer block
        if (age < 18) {
            println("$name is a minor.")
        } else {
            println("$name is an adult.")
        }
    }
}

fun main() {
    // Creates an instance of the Person class
    Person("John", 30)
    // Person created: John, age 30.
    // John is an adult.
}
//sampleEnd

В блоках инициализации можно использовать параметры первичного конструктора. Например, в приведённом выше коде первый и второй блоки инициализации используют параметры name и age первичного конструктора.

Блоки init часто используются для проверки данных. Например, можно вызвать функцию require:

class Person(val age: Int) {
    init {
        require(age > 0) { "age must be positive" }
    }
}

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

В Kotlin вторичные конструкторы — это дополнительные конструкторы класса, помимо первичного. Они полезны, когда нужно несколько способов инициализации класса, а также для взаимодействия с Java.

Чтобы объявить вторичный конструктор, используйте ключевое слово constructor внутри тела класса и укажите параметры конструктора в круглых скобках (). Логику конструктора поместите в фигурные скобки {}:

// Class header with a primary constructor that initializes name and age
class Person(val name: String, var age: Int) {

    // Secondary constructor that takes age as a
    // String and converts it to an Int
    constructor(name: String, age: String) : this(name, age.toIntOrNull() ?: 0) {
        println("$name created with converted age: ${this.age}")
    }
}

fun main() {
    // Uses the secondary constructor with age as a String
    Person("Bob", "8")
    // Bob created with converted age: 8
}

В выражении age.toIntOrNull() ?: 0 используется оператор Elvis. Подробнее см. в разделе Безопасность работы с null.

В приведённом выше коде вторичный конструктор делегирует вызов первичному с помощью ключевого слова this, передавая name и значение age, преобразованное в целое число.

В Kotlin вторичные конструкторы должны делегировать вызов первичному конструктору. Благодаря этому вся логика инициализации первичного конструктора выполняется до запуска логики вторичного конструктора.

Делегирование конструктора может быть:

  • Прямым, когда вторичный конструктор сразу вызывает первичный конструктор.

  • Косвенным, когда один вторичный конструктор вызывает другой, а тот делегирует вызов первичному конструктору.

Ниже показано, как работает прямое и косвенное делегирование:

// Class header with a primary constructor that initializes name and age
class Person(
    val name: String,
    var age: Int
) {
    // Secondary constructor with direct delegation 
    // to the primary constructor
    constructor(name: String) : this(name, 0) {
        println("Person created with default age: $age and name: $name.")
    }

    // Secondary constructor with indirect delegation: 
    // this("Bob") -> constructor(name: String) -> primary constructor
    constructor() : this("Bob") {
        println("New person created with default age: $age and name: $name.")
    }
}

fun main() {
    // Creates an instance based on the direct delegation
    Person("Alice")
    // Person created with default age: 0 and name: Alice.

    // Creates an instance based on the indirect delegation
    Person()
    // Person created with default age: 0 and name: Bob.
    // New person created with default age: 0 and name: Bob.
}

В классах с блоками инициализации (init {}) код этих блоков становится частью первичного конструктора. Поскольку вторичные конструкторы сначала делегируют вызов первичному, все блоки инициализации и инициализаторы свойств выполняются до тела вторичного конструктора. Даже если у класса нет первичного конструктора, делегирование всё равно происходит неявно:

// Class header with no primary constructor
class Person {
    // Initializer block runs when an instance is created
    init {
        // Runs before the secondary constructor
        println("1. First initializer block runs")
    }

    // Secondary constructor that takes an integer parameter
    constructor(i: Int) {
        // Runs after the initializer block
        println("2. Person $i is created")
    }
}

fun main() {
    // Creates an instance of the Person class
    Person(1)
    // 1. First initializer block runs
    // 2. Person 1 created
}

Классы без конструкторов

У классов, в которых не объявлены конструкторы (первичный или вторичные), есть неявный первичный конструктор без параметров:

// Class with no explicit constructors
class Person {
    // No primary or secondary constructors declared
}

fun main() {
    // Creates an instance of the Person class 
    // using the implicit primary constructor
    val person = Person()
}

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

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

На JVM, если у всех параметров первичного конструктора заданы значения по умолчанию, компилятор неявно предоставляет конструктор без параметров, который использует эти значения.

Это упрощает использование Kotlin с такими библиотеками, как Jackson или Spring Data JPA, которые создают экземпляры классов с помощью конструкторов без параметров.

В следующем примере Kotlin неявно предоставляет конструктор без параметров Person(), который использует значение по умолчанию "":

class Person(val personName: String = "")

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

Наследование классов в Kotlin позволяет создать новый класс (производный класс) на основе существующего (базового класса), унаследовав его свойства и функции, а также добавив или изменив поведение.

Подробные сведения об иерархиях наследования и использовании ключевого слова open см. в разделе Наследование.

Абстрактные классы

В Kotlin абстрактные классы нельзя создавать напрямую. Они предназначены для наследования другими классами, которые определяют их фактическое поведение. Такое поведение называется реализацией.

В абстрактном классе можно объявлять абстрактные свойства и функции, которые должны быть реализованы в подклассах.

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

abstract class Person(val name: String, val age: Int)

Абстрактный класс может содержать как абстрактные, так и неабстрактные члены (свойства и функции). Чтобы объявить член абстрактным, необходимо явно использовать ключевое слово abstract.

Абстрактные классы или функции не нужно помечать ключевым словом open, поскольку по умолчанию они неявно допускают наследование. Подробнее о ключевом слове open см. в разделе Наследование.

У абстрактных членов нет реализации в абстрактном классе. Реализацию можно определить в подклассе или наследующем классе с помощью override функции или свойства:

// Abstract class with a primary constructor that declares name and age
abstract class Person(
    val name: String,
    val age: Int
) {
    // Abstract member 
    // Doesn't provide implementation,
    // and it must be implemented by subclasses
    abstract fun introduce()

    // Non-abstract member (has an implementation)
    fun greet() {
        println("Hello, my name is $name.")
    }
}

// Subclass that provides an implementation for the abstract member
class Student(
    name: String,
    age: Int,
    val school: String
) : Person(name, age) {
    override fun introduce() {
        println("I am $name, $age years old, and I study at $school.")
    }
}

fun main() {
    // Creates an instance of the Student class
    val student = Student("Alice", 20, "Engineering University")
    
    // Calls the non-abstract member
    student.greet()
    // Hello, my name is Alice.
    
    // Calls the overridden abstract member
    student.introduce()
    // I am Alice, 20 years old, and I study at Engineering University.
}

Объекты-компаньоны

В Kotlin у каждого класса может быть объект-компаньон. Объекты-компаньоны — это разновидность объявления объекта, позволяющая обращаться к его членам по имени класса без создания экземпляра класса.

Предположим, вам нужно написать функцию, которую можно вызвать без создания экземпляра класса, но которая логически связана с классом (например, фабричную функцию). В этом случае её можно объявить внутри объявления объекта-компаньона внутри класса:

// Class with a primary constructor that declares the name property
class Person(
    val name: String
) {
    // Class body with a companion object
    companion object {
        fun createAnonymous() = Person("Anonymous")
    }
}

fun main() {
    // Calls the function without creating an instance of the class
    val anonymous = Person.createAnonymous()
    println(anonymous.name)
    // Anonymous
}

Если объявить объект-компаньон внутри класса, обращаться к его членам можно, указывая только имя класса в качестве квалификатора.

Подробнее см. в разделе Объекты-компаньоны.

12 августа 2026 г.
Проверка неиспользуемого возвращаемого значенияКлассы данных

© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/classes.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API