Menu
Coddy logo textTech

Методы по умолчанию

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

Метод интерфейса может иметь тело. Эта реализация по умолчанию используется каждым классом, который её не переопределяет:

interface Greeter {
    val name: String
    fun greet() = "Hello, I am $name"
}
class Robot(override val name: String) : Greeter
class Pirate(override val name: String) : Greeter {
    override fun greet() = "Ahoy! $name here"
}

Внутри main:

println(Robot("R2").greet())
println(Pirate("Anne").greet())

Вывод:

Hello, I am R2
Ahoy! Anne here

Методы по умолчанию записываются с использованием других членов интерфейса. Класс предоставляет несколько отличающихся членов и получает остальные:

interface Priced {
    val cents: Int
    fun formatted() = "$%d.%02d".format(cents / 100, cents % 100)
    fun isAffordable(budget: Int) = cents <= budget
}
class Coffee : Priced {
    override val cents = 450
}

Внутри main:

val c = Coffee()
println(c.formatted())
println(c.isAffordable(400))

Результат:

$4.50
false

У свойств может быть геттер по умолчанию, но у интерфейса нет резервных полей, поэтому он не может хранить значение. Свойство с инициализатором не компилируется; геттер, вычисляющий значение, — компилируется:

interface Box {
    val width: Int
    val height: Int
    val area: Int
        get() = width * height
    // val count = 0      // error: инициализаторы свойств не допускаются в интерфейсах
}
class Tile(override val width: Int, override val height: Int) : Box

Внутри main:

println(Tile(3, 4).area)

Вывод:

12

Переопределение всё ещё может использовать реализацию по умолчанию. Внутри класса super.method() вызывает версию интерфейса:

interface Priced {
    val cents: Int
    fun formatted() = "$%d.%02d".format(cents / 100, cents % 100)
}
class Coffee : Priced {
    override val cents = 450
    override fun formatted() = "coffee " + super.formatted()
}

Внутри main:

println(Coffee().formatted())

Вывод:

coffee $4.50
challenge icon

Задание

Легко

Интерфейс Priced содержит price (в центах). Добавьте для него реализацию formatted() по умолчанию, которая возвращает $4.50, и реализацию isAffordable(budget) по умолчанию, которая возвращает, не превышает ли цена бюджет. Coffee стоит 450 и заменяет formatted() на coffee $4.50, повторно используя реализацию по умолчанию через super. Sandwich(price) использует обе реализации по умолчанию.

Предоставленный код считывает бюджет в центах, а затем строки coffee или sandwich,650. Для каждого товара он выводит formatted() и yes или no.

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

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

fun main() {
    // Предоставленный код ввода/вывода: оставьте его как есть
    val input = generateSequence(::readLine).toList()
    val budget = input[0].toInt()
    for (line in input.drop(1)) {
        val p = line.split(",")
        val item: Priced = if (p[0] == "coffee") Coffee() else Sandwich(p[1].toInt())
        println("${item.formatted()} ${if (item.isAffordable(budget)) "yes" else "no"}")
    }
}
quiz iconПроверьте себя

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

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

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