Kotlin: Абстрактные классы и интерфейсы

Интерфейсы

Интерфейсы описывают функции без реализации, представляя собой «скелеты» функций, реализуемых в других классах. Создадим интерфейс UserInfoProvider в файле UserInfoProvider.kt:

interface UserInfoProvider {
    fun printInfo(user: User) 
}

Этот интерфейс содержит функцию printInfo, принимающую объект класса User (предполагается, что класс User определён ранее) и выводящую информацию о пользователе. Даже пустой интерфейс корректен.

Реализация интерфейса

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

class MainProvider : UserInfoProvider {
    // Реализация функции printInfo
}

Необходимо реализовать все функции интерфейса; в противном случае компилятор выдаст ошибку. Реализация printInfo:

override fun printInfo(user: User) {
    println("Message was called") 
    user.printUser() // Вызов функции класса User
}

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

Альтернативой интерфейсам являются абстрактные классы, объявляемые с помощью ключевого слова abstract. Они позволяют описывать функции без реализации, оставляя её для классов-наследников. Создание объекта абстрактного класса невозможно.

Пример попытки создания объекта абстрактного класса:

// ... абстрактный класс ...

fun main() {
    val mainProvider = MainProvider() // Ошибка компиляции
}

Реализация функций в интерфейсе

В Kotlin можно добавлять реализацию функций непосредственно в интерфейс:

interface UserInfoProvider {
    fun printInfo(user: User) = println("Message was called")
}

Реализация printInfo находится в интерфейсе, но её можно переопределить в классах, используя override. super позволяет вызвать реализацию из интерфейса:

override fun printInfo(user: User) {
    super.printInfo(user) // Вызов реализации из интерфейса
    println("Дополнительный код") 
}

Переменные в интерфейсах

В интерфейсах можно объявлять переменные без присвоения значений. Значения устанавливаются в реализующих классах с использованием val или var и методов get/set:

interface UserInfoProvider {
    val info: String
}

class MainProvider : UserInfoProvider {
    override val info: String = "Message was called"
}

Реализация нескольких интерфейсов

Класс может реализовывать несколько интерфейсов, перечисляя их через запятую:

interface DbConnection {
    fun getConnection(): String
}

class MainProvider : UserInfoProvider, DbConnection {
    // Реализация функций из обоих интерфейсов
    override fun getConnection(): String = "Db connected"
}

Проверка типа объекта

Для проверки типа объекта используется is:

fun checkDataTypes(obj: MainProvider) {
    if (obj is UserInfoProvider) {
        obj.printInfo(User())
    }
    if (obj is DbConnection) {
        println(obj.getConnection())
    }
}

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

Что будем искать? Например,программа