LoginSignup
11
9

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-07-31

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

  • 実装するオブジェクトの協会におけるプロトコル(規約、取り決め)を表現するもの
  • インタフェースのメンバは基本抽象メンバ(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) // [移譲]

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

11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9