🍻

Kotlin の interface に private, protected, internal メソッドを定義する

2021/07/15に公開

Kotlin の interface に private, protected, internal メソッドを定義したいなってことありますよね?
僕はライブラリを作ってると稀によくあります。

でも普通に定義しようとしてもコンパイルエラーになってしまいますよね。
そんな時に便利なテクニックをご紹介します。

TL;DR

これらの方法で interface に private, protected, internal メソッドを定義できます。

interface Interface {
    fun publicMethod() {
        privateMethod()
    }
    private fun privateMethod() = Unit
    fun Interface.protectedMethod()
}

internal fun Interface.internalMethod() = Unit

それぞれについての説明は以下を参照してください。

interface に private メソッドを定義する

private メソッドは実は定義できます。
public メソッドのデフォルト実装からのみ呼び出せます。

interface Interface {
    fun publicMethod() {
        privateMethod()
    }
    private fun privateMethod() = Unit
}

interface に protected メソッドを定義する

proteced メソッドは interface 内に interface の拡張関数として定義します。
基本的には interface を実装したクラス内で呼び出せます。

interface Interface {
    fun Interface.protectedMethod()
}

class Implementation : Interface {
    override fun Interface.protectedMethod() = Unit
    
    init {
        protectedMethod()
    }
}

以下の例外があるため、完全な protected メソッドではありません。
スコープ関数の with で this を interface 実装クラスにすることで interface 実装クラス外からも呼び出せます。

fun youCanCallProtectedMethodByWithTechnique() {
    with(Implementation()){
        protectedMethod()
    }
}

interface に internal メソッドを定義する

internal メソッドは interface 外に interface の拡張関数として定義します。
可視性は通常の internal メソッドと同様です。

interface Interface
internal fun Interface.internalMethod() = Unit

class Implementation : Interface {
    init {
        internalMethod()
    }
}

// internal メソッドの定義と同じモジュール
fun methodInSameModule() {
    Implementation().internalMethod()
}

// internal メソッドの定義と異なるモジュール
fun methodInOtherModule() {
    Implementation().internalMethod() // コンパイルエラー: 参照不可
}

おわりに

Let's enjoy Kotlin life! 🍻

Discussion