Menu
Coddy logo textTech

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

Часть раздела Объектно-ориентированное программирование путешествия по Kotlin на Coddy. Урок 5 из 57.

Класс может предоставлять дополнительные способы создания экземпляров с помощью вторичных конструкторов, объявленных с помощью constructor. Каждый из них должен вызывать первичный конструктор с помощью this(...):

class Temperature(val celsius: Double) {
    constructor(fahrenheit: Int) : this((fahrenheit - 32) * 5 / 9.0)
}

Внутри main:

println(Temperature(20.0).celsius)
println(Temperature(212).celsius)

Вывод:

20.0
100.0

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

class Color(val r: Int, val g: Int, val b: Int) {
    constructor(gray: Int) : this(gray, gray, gray)
    constructor(hex: String) : this(hex.substring(0, 2).toInt(16), hex.substring(2, 4).toInt(16), hex.substring(4, 6).toInt(16))

    fun label() = "rgb($r, $g, $b)"
}

Внутри main:

println(Color(128).label())
println(Color("FF8000").label())

Результат:

rgb(128, 128, 128)
rgb(255, 128, 0)

Сначала выполняются первичный конструктор и его блоки init, затем тело вторичного конструктора:

class Log(val name: String) {
    init { println("primary: $name") }
    constructor(id: Int) : this("log-$id") {
        println("secondary: $id")
    }
}

Внутри main:

Log(7)

Вывод:

primary: log-7
secondary: 7

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

class Size(val w: Int, val h: Int) {
    constructor(side: Int) : this(side, side)   // Size(3) -> квадрат
    // constructor(w: Int) : this(w, 1)        // ошибка: та же сигнатура, что и выше
}
challenge icon

Задание

Легко

Дополните класс Duration(val seconds: Int) дополнительным конструктором (minutes: Int, seconds: Int) и ещё одним конструктором, который принимает текст вроде 1:30 или 2:05:10 (часы: минуты: секунды). Добавьте format(), возвращающий h:mm:ss с минутами и секундами, записанными двумя цифрами.

Предоставленный код считывает длительности в виде текста с одним или двумя двоеточиями, создаёт каждую из них с помощью текстового конструктора и выводит format(), затем выводит total и отформатированную сумму.

Ваш код должен находиться в Duration.kt. В Main.kt содержится предоставленный код ввода/вывода, и его нельзя изменять.

Попробуйте сами

fun main() {
    // Предоставленный код ввода/вывода: оставьте его как есть
    val input = generateSequence(::readLine).toList()
    var total = 0
    for (line in input) {
        val d = Duration(line)
        println(d.format())
        total += d.seconds
    }
    println("total " + Duration(total).format())
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Песочница Kotlin