Edit Page

インターフェース

Kotlinでのインタフェースは、Java 8と非常によく似ています。インタフェースは抽象メソッドの宣言と同様に、メソッドの実装を含めることができます。抽象クラスと違って、インタフェースは状態を持てません。インタフェースはプロパティを持つことができますが、これらは abstract であること、またはアクセサの実装を提供することが必要です。

インタフェースは、 interface キーワードを使用して定義されます。

interface MyInterface {
    fun bar()
    fun foo() {
      // 本体は任意
    }
}

インタフェースの実装

クラスやオブジェクトは、1つまたは複数のインターフェイスを実装することができます:

class Child : MyInterface {
   override fun bar() {
      // 本体
   }
}

インターフェイス内のプロパティ

インターフェイス内にプロパティを宣言することができます。インタフェースで宣言されたプロパティは、 abstract にすることも、アクセサの実装を提供することもできます。インタフェース内で宣言されたプロパティはバッキングフィールドを持つことはできず、それ故にインタフェース内で宣言されたアクセサはそれらを参照できません。

interface MyInterface {
    val property: Int // abstract

    val propertyWithImplementation: String
        get() = "foo"

    fun foo() {
        print(property)
    }
}

class Child : MyInterface {
    override val property: 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()
  }
}

インタフェース AB は、両方とも関数 foo()bar() を宣言しています。両方とも foo() を実装していますが、 B のみが bar() を実装しています。( bar()A では abstract としてマークされていません。これは関数が本体を持たないときのインタフェースのデフォルトだからです。) さて、もし具体クラス CA から得れば、 bar() をオーバライドし、実装を提供しなければならないことは明らかです。そしてもし DAB から得れば、 bar() をオーバライドする必要はありません。なぜなら1つの実装を継承したからです。 しかし foo() の実装を2つ継承してしまったため、コンパイラはどっちを選んだら良いかわかりません。したがって foo() のオーバライドが強制され、何が欲しいのかを明示する必要があります。