Skip to content

Latest commit

 

History

History
106 lines (84 loc) · 5.68 KB

interfaces.md

File metadata and controls

106 lines (84 loc) · 5.68 KB
type layout category title url
doc
reference
Syntax
Интерфейсы

Интерфейсы

Интерфейсы в Kotlin очень похожи на интерфейсы в Java 8. Они могут содержать абстрактные методы, методы с реализацией. Главное отличие интерфейсов от абстрактных классов заключается в невозможности хранения переменных экземпляров. Они могут иметь свойства, но те должны быть либо абстрактными, либо предоставлять реализацию методов доступа.

Интерфейс определяется ключевым словом interface:

interface MyInterface {
    fun bar()
    fun foo() {
      // необязательное тело
    }
}

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

Класс или объект могут реализовать любое количество интерфейсов:

class Child : MyInterface {
    override fun bar() {
        // тело
    }
}

Свойства в интерфейсах

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

interface MyInterface {
    val prop: Int // абстрактное свойство

    val propertyWithImplementation: String
        get() = "foo"

    fun foo() {
        print(prop)
    }
}

class Child : MyInterface {
    override val prop: Int = 29
}

Устранение противоречий при переопределении

Когда мы объявлем большое количество типов в списке нашего супертипа, может так выйти, что мы допустим более одной реализации одного и того же метода. Например:

interface A {
    fun foo() { print("A") }
    fun bar()
}

interface B {
    fun foo() { print("B") }
    fun bar() { print("bar") }
}

class C : A {
    override fun bar() { print("bar") }
}

class D : A, B {
    override fun foo() {
        super<A>.foo()
        super<B>.foo()
    }
    
    override fun bar() {
        super<B>.bar()
    }
}

Оба интерфейса A и B объявляют функции foo() и bar(). Оба реализуют foo(), но только B содержит реализацию bar() (bar() не отмечен как абстрактный метод в интерфейсе A, потому что в интерфейсах это подразумевается по умолчанию, если у функции нет тела). Теперь, если мы унаследуемся каким-нибудь классом C от интерфейса A, нам, очевидно, придётся переопределять метод bar(), обеспечивая его реализацию.

Однако, если мы унаследуемся классом D от интерфейсов A и B, нам надо будет переопределять все методы, которые мы унаследовали от этих интерфейсов. Это правило касается как тех методов, у которых имеется только одна реализация (bar()), так и тех, у которых есть несколько реализаций (foo()).