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