Интерфейсы
Интерфейсы описывают функции без реализации, представляя собой «скелеты» функций, реализуемых в других классах. Создадим интерфейс 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.