Kotlinのinterfaceについて

採用はこちら

Kotlinの interface(インターフェース) は、クラスが持つべき機能を定義するための仕組みです。

簡単に言うと、クラスに対して「この機能を必ず実装してください」という 契約(contract) を定義するものです。

interface自体は通常、具体的な処理の主体ではなく、振る舞いの仕様だけを定義する役割を持ちます。

例えば次のように定義します。

interface Animal {
    fun makeSound()
}

このinterfaceを実装するクラスは、必ず makeSound() を実装する必要があります。

目次

interfaceの基本構文

interfaceの定義

interface InterfaceName {
    関数
    プロパティ
}

interfaceの実装

クラスがinterfaceを実装する場合は : を使います。

class ClassName : InterfaceName {
}

基本的な使用例

まず、動物の鳴き声を表すinterfaceを作ります。

interface Animal {
    fun makeSound()
}

このinterfaceを実装するクラスを作ります。

class Dog : Animal {
    override fun makeSound() {
        println("Woof")
    }
}

class Cat : Animal {
    override fun makeSound() {
        println("Meow")
    }
}

使用例

fun main() {
    val dog = Dog()
    val cat = Cat()

    dog.makeSound()
    cat.makeSound()
}

出力

Woof
Meow

このように、同じinterfaceを実装したクラスは共通の振る舞いを持つことになります。

Kotlin interfaceの特徴

Kotlinのinterfaceは、単なる抽象契約だけでなく、いくつかの特徴を持っています。

主な特徴は次の通りです。

特徴説明
メソッド実装可能デフォルト実装を書くことができる
プロパティ宣言可能ただし実体フィールドは持てない
多重実装可能複数のinterfaceを実装できる
抽象指定不要実装がなければ自動的にabstractになる
コンストラクタなしinterfaceはコンストラクタを持てない

interfaceのメソッド

interfaceでは関数を宣言できます。

実装がない場合、その関数は 抽象メソッド になります。

interface Animal {
    fun makeSound()
}

実装するクラスでは override が必要です。

class Dog : Animal {

    override fun makeSound() {
        println("Woof")
    }

}

デフォルト実装(Default Implementation)

Kotlinのinterfaceでは、関数の実装を書くこともできます。

interface Animal {

    fun makeSound()

    fun sleep() {
        println("Sleeping")
    }

}

この場合、実装クラスは sleep() を必ずしも override する必要はありません。

class Dog : Animal {

    override fun makeSound() {
        println("Woof")
    }

}

使用

val dog = Dog()
dog.sleep()

出力

Sleeping

つまり、interfaceは 共通処理を持つことも可能です。

interfaceのプロパティ

Kotlinのinterfaceではプロパティを宣言できます。

interface Person {
    val name: String
}

ただし重要な点として、interfaceは 値を保持するフィールド(backing field)を持てません

そのため、プロパティは次のどちらかになります。

  1. 実装クラス側で値を提供する
  2. getterを使って計算する

実装クラス側で値を提供する例

interface Person {
    val name: String
}

class User(override val name: String) : Person

getterで値を計算する例

interface Person {

    val name: String

    val greeting: String
        get() = "Hello $name"

}

ここで greeting は値を保持しているわけではなく、getterで計算して返しているだけです。

interfaceの多重実装

Kotlinでは

  • クラスの多重継承はできない
  • interfaceの多重実装はできる

という特徴があります。

interface Flyable {
    fun fly()
}

interface Swimmable {
    fun swim()
}

class Duck : Flyable, Swimmable {

    override fun fly() {
        println("Flying")
    }

    override fun swim() {
        println("Swimming")
    }

}

複数interfaceでメソッドが衝突する場合

複数のinterfaceが同じメソッドを持つ場合、クラスはそれを明示的に解決する必要があります。

interface A {
    fun hello() {
        println("Hello from A")
    }
}

interface B {
    fun hello() {
        println("Hello from B")
    }
}

実装

class Test : A, B {

    override fun hello() {
        super<A>.hello()
        super<B>.hello()
    }

}

このように、どのinterfaceの実装を使うかを明示します。

interfaceとabstract classの違い

Kotlinではinterfaceと抽象クラスは似ていますが役割が異なります。

項目interfaceabstract class
フィールド持てない持てる
コンストラクタなしあり
多重継承可能不可
用途振る舞いの契約共通ロジック

簡単に言うと

  • interface → 機能の仕様
  • abstract class → 共通実装

という役割になります。

fun interface(関数型インターフェース)

Kotlinには 関数型インターフェース があります。

fun interface Printer {
    fun print(text: String)
}

このようなinterfaceは 抽象関数が1つだけ という条件を満たします。

使用例

val printer = Printer { text ->
    println(text)
}

printer.print("Hello")

このように ラムダ式で実装できる のが特徴です。

この仕組みを SAM変換(Single Abstract Method) と呼びます。

interfaceを使う主な目的

実務ではinterfaceは次の目的でよく使われます。

依存関係の分離

interface Logger {
    fun log(message: String)
}

実装

FileLogger
ConsoleLogger
CloudLogger

実装を自由に差し替えられるようになります。

テストをしやすくする

interfaceを使うことで、テスト用の実装を簡単に作れます。

class FakeUserRepository : UserRepository

アーキテクチャ設計

特に次のような設計で使われます。

  • Clean Architecture
  • Repository Pattern
  • Dependency Injection

まとめ

Kotlinのinterfaceは、クラスの振る舞いを定義するための重要な仕組みです。

主なポイントを整理すると次の通りです。

  • クラスが実装すべき機能の契約を定義する
  • 関数は実装を持つこともできる
  • プロパティは宣言できるがフィールドは持てない
  • 複数のinterfaceを実装できる
  • fun interface を使うとラムダで実装できる

以上、Kotlinのinterfaceについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次