Перейти до вмісту

Освоюємо Kotlin/Інтерфейси

Матеріал з Вікіпідручника


Інтерфейси в Kotlin — це абстракція подібна до абстрактних класів, але з деякими відмінностями. Інтерфейси можуть мати оголошення абстрактних методів та їхню реалізацю, проте на відміну від абстрактних класів, інтерфейси не можуть зберігати стан (тобто мати ініціалізовані властивості, хоча самі властивості можуть бути задекларовані). Властивості мають бути абстрактними або спадкоємці мають їх реалізувати. Інтерфейси, також, на відміну від абстрактних класів не можуть мати конструкторів. Основна мета інтерфейсів задавати певну договорену спільну абстракцію для нащадків( певну домовленість про властивості і функції), що кожен з класів нащадків може реалізовувати по своєму. Таким чином класи, що реалізовують інтерфейси, зберігають певну сумісність і отримується можливість використовувати одні класи замість інших з використанням інтерфейсних змінних (що зветься поліморфізмом).

Оголошення інтерфейсу

[ред.]

Інтерфейси оголошуються з ключовим словом Interface:

interface Person{
    var name: String 
    var age: Int 
    fun introduce() // абстрактна функція, ключове слово abstract можна не вказувати
    fun details(){   // відкрита функція для заміщення, ключове слово open необов'язкове
        println ("Ім'я: $name, вік: $age")
    }
}

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

[ред.]

Щоб реалізувати інтерфейс використовується то же синтаксис, що і при успадкуванні, тобто після двох крапок, необхідно вказати назву інтерфейсу. Клас має реалізувати нереалізовані(абстрактні) функції інтерфейсу.

Наступний приклад демонструє створення класу Doctor, що реалізовує інтерфейс Person. Doctor заміщає властивості інтерфейсу та реалізовує функцію introduce().

interface Person{
    var name: String
    var age: Int
    fun introduce()
    fun details(){
        println ("Ім'я: $name, вік: $age")
    }
}

class Doctor(override var name:String, override var age:Int, var specialization:String):Person{
    override fun introduce() {
        println ("Мене звати: $name і мій вік: $age років, моя спеціалізація: $specialization")
    }
}

fun main(){
    val doctor=Doctor("Анатолій Непийвода", 56, "терапевт")
    doctor.introduce() // викликаємо заміщену функцію
    doctor.details()   // викликаємо успадковану функцію з інтерфейсу
}
Standard input or output Результат:
Мене звати: Анатолій Непийвода і мій вік: 56 років, моя спеціалізація: терапевт
Ім'я: Анатолій Непийвода, вік: 56

Клас може реалізуовувати безліч інтерфейсів, на відміну від механізму спадкування класів, де можна спадкуватися лише від одного класу(повноцінного або абстрактного)

Спадкування інтерфейсів

[ред.]

Інтерфейси можуть походити від інших інтерфейсів, розширяючи їх таким чином.

interface Entity{
    val name:String
}

interface Person:Entity{
    var firstName: String
    var lastName: String
    override val name: String get() = "$firstName $lastName"
    fun introduce()
}

class Doctor(override var firstName:String, override var lastName:String, var specialization:String):Person{
    override fun introduce() {
        println ("Мене звати: $name, я $specialization")
    }
}

fun main(){
    val doctor=Doctor("Анатолій", "Непийвода", "терапевт")
    doctor.introduce() // викликаємо заміщену функцію
}
Standard input or output Результат:
Мене звати: Анатолій Непийвода, я терапевт

Вирішення конфліктів заміщення функцій

[ред.]

Якщо реалізується кілька інтерфейсів, які містять функції з однаковими назвами і є необхідність звернутися до певної функції, то використовується ключове слово super з вказанням назви інтерфейсу і назви функції:

interface  Individual{
    fun introduce(){
        println("Individual")
    }
}

interface Person{
    fun introduce(){
        println("person")
    }
}

class Doctor:Person, Individual{
    override fun introduce() {
        super<Individual>.introduce()
        super<Person>.introduce()
        println ("doctor")
    }
}

Джерела

[ред.]