Help us understand the problem. What is going on with this article?

Kotlinまとめ - 文法詳解 - インタフェース

More than 1 year has passed since last update.

インタフェースの定義と実装

  • 実装するオブジェクトの協会におけるプロトコル(規約、取り決め)を表現するもの
  • インタフェースのメンバは基本抽象メンバ(abstructを書かないのが普通)
    • 直接インスタンス化できない
interface Greeter {
    val language: String
    fun sayHello(target: String)
}

class EnglishGreeter: Greeter {
    override val language: String = "English"
    override fun sayHello(target: String) {
        println("Hello, $target")
    }
}
  • 抽象クラスとの違い
    • インタフェースにはコンストラクタがない
    • 継承可能なクラスは1つ。準拠可能なインタフェースは1つ以上
      複数のインタフェースを実装する場合はカンマで区切る

デフォルト実装とコンフリクト回避

  • ①インタフェースは複数実装できるが、同名のメンバをもつ別々のインタフェースを実装しようとする
    • →問題なし
interface Foo {
    fun execute()
}

interface Bar {
    fun execute()
}

class FooBar: Foo, Bar {
    override fun execute() {
        println("FooBar")
    }
}
  • ②同一のメンバをもつクラスとインタフェースをそれぞれ実装しようとする
    • →問題なし。スーパークラスに実装があるので、サブクラスでの実装は任意
interface Foo {
    fun execute()
}

open class SuperClass {
    open fun execute() {
        println("SuperClass")
    }
}

class FooSubClass: SuperClass(), Foo {}
  • ③実装がある同一のメンバをもつインタフェースをそれぞれ実装しようとする
    • →デフォルトの実装があるがオーバーライドする必要がある
interface Foo {
    fun execute() {
        println("Foo")
    }
}

interface Bar {
    fun execute() {
        println("Bar")
    }
}

class FooBar: Foo, Bar {
    override fun execute() {
        super<Foo>.execute()
    }
}
  • さらっと出てきたがインタフェースは実装を持つことができる
    • メソッド
    • バッキングフィールドを持たないプロパティ

インタフェースの継承

継承元のメンバを受け継ぐ

interface Foo {
    fun aaa()
    fun bbb()
}

interface Bar: Foo {
    override fun aaa() {}
    fun ccc()
}

class Baz: Bar {
    override fun bbb() {}
    override fun ccc() {}
}

デリゲーション

  • オーバーライドしていないメンバは、デリゲーションによって受け取ったものと同じ処理をする
    という処理が書ける
  • 正直使い所が難しい。
    移譲することによって影響範囲が大きくなりやすくなりそうでメンテナンスしづらそうなイメージが湧いた
interface Greeter {
    fun sayHello(target: String)
    fun sayHello()
}

class JapaneseGreeter: Greeter {

    override fun sayHello() {
        this.sayHello("匿名さん")
    }

    override fun sayHello(target: String) {
        println("こんにちは、$target!")
    }
}

// sayHello()を実装していないが、デフォルトの動作はコンストラクタで受け取ったgreeterの処理を実行する
class GreeterWithRecording(private val greeter: Greeter): Greeter by greeter {

    private val _targets: MutableSet<String> = mutableSetOf()
    val targets: Set<String>
        get() = _targets

    override fun sayHello(target: String) {
        _targets += target
        greeter.sayHello(target)
    }
}

val japanese = JapaneseGreeter()
val greeter = GreeterWithRecording(japanese)
greeter.sayHello()       // こんにちは、匿名さん!
greeter.sayHello("移譲")  // こんにちは、移譲さん!
println(greeter.targets) // [移譲]

← 文法詳解 - 継承と抽象クラス || 文法詳解 - ジェネリクス →

hicka04
東京でiOSアプリメインで開発してます
nifty
インターネット接続やブログといったインターネット関連サービスを開発・提供している企業です。
http://www.nifty.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away