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)を持てません。
そのため、プロパティは次のどちらかになります。
- 実装クラス側で値を提供する
- 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と抽象クラスは似ていますが役割が異なります。
| 項目 | interface | abstract 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についてでした。
最後までお読みいただき、ありがとうございました。










