Kotlinのインラインクラス

1.概要

Kotlin 1.3では、https://kotlinlang.org/docs/reference/inline-classes.html[インラインクラス]と呼ばれる実験的な新しいタイプのクラスがあります。

このチュートリアルでは、インラインクラスの使用法とその制限事項に焦点を当てます。

2.セットアップ

前述したように、インラインクラスはKotlinの実験的な機能です。結果として、コンパイラは機能の実験的な状態を示す warning をスローします。

この警告を回避するために、次のhttps://kotlinlang.org/docs/reference/using-maven.html#specifying-compiler-options[Mavenコンパイラオプション]を設定に追加できます。

<configuration>
    <args>
        <arg>-XXLanguage:+InlineClasses</arg>
    </args>
</configuration>

3.インラインクラスとは

インラインクラスは、型をラップする方法を提供し、それによって機能を追加し、それ自体で新しい型を作成します。

通常の(インライン化されていない)ラッパーとは対照的に、パフォーマンスが向上するという利点があります。これは、データがその用途にインライン化されているため、結果として生成されるコンパイル済みコードでオブジェクトのインスタンス化がスキップされるためです。

半径を表す Double 型のプロパティを持つ InlinedCircleRadius というインラインクラスの例を見てみましょう。

val circleRadius = InlinedCircleRadius(5.5)

JVMの場合、私たちのコードは実際には次のとおりです。

val circleRadius = 5.5

基になる値がインライン化されているため、 InlinedCircleRadius がコンパイル済みコードでインスタンス化されていないことに注意してください。インスタンス化に伴うパフォーマンスの低下から解放されます。

3.1. 使用例

インラインクラスとは何かがわかったので、次にそれらの使用法について説明します。

  • プライマリコンストラクタで初期化された単一のプロパティは、インラインクラスの基本的な要件です。 __. __単一のプロパティは、実行時にクラスインスタンスを表します。

したがって、正しい定義をするために、単一行のコードを使用できます。

inline class InlineDoubleWrapper(val doubleValue : Double)

Double オブジェクトに対する単純なラッパーとして InlineDoubleWrapper を定義し、それに inline キーワードを適用しました。最後に、このクラスをコード内で追加の変更なしに使用できます。

@Test
fun whenInclineClassIsUsed__ThenPropertyIsReadCorrectly() {
    val piDoubleValue = InlineDoubleWrapper(3.14)
    assertEquals(3.14, piDoubleValue.doubleValue)
}

4.クラスメンバー

これまでは、単純なラッパーと同じようにインラインクラスを使用していました。しかし、彼らはそれ以上のものです。 ** 次の例では、直径を表すプロパティと円の面積を返す関数を定義します。

inline class CircleRadius(private val circleRadius : Double) {
    val diameterOfCircle get() = 2 **  circleRadius
    fun areaOfCircle = 3.14 **  circleRadius **  circleRadius
}

これで diameterOfCircle プロパティのテストを作成しましょう。これは CircleRadius インラインクラスをインスタンス化してからプロパティを呼び出します。

@Test
fun givenRadius__ThenDiameterIsCorrectlyCalculated() {
    val radius = CircleRadius(5.0)
    assertEquals(10.0, radius.diameterOfCircle)
}

これが areaOfCircle 関数の簡単なテストです。

@Test
fun givenRadius__ThenAreaIsCorrectlyCalculated() {
    val radius = CircleRadius(5.0)
    assertEquals(78.5, radius.areaOfCircle())
}

ただし、インラインクラス内で定義できるものとできないものにはいくつかの制限があります。 ** プロパティと関数は許可されていますが、 init ブロック、内部クラス、およびhttps://kotlinlang.org/docs/reference/properties.html#backing-fields[backing fields]は許可されていません。

5.継承

インラインクラスはインターフェイスからしか継承できないことに注意することが重要です。また、サブクラスを作成できないため、インラインクラスも事実上最終的なものになります。

メソッド draw() を持つインタフェース Drawable が与えられた場合、このメソッドは CircleRadius クラスに実装します。

interface Drawable {
    fun draw()
}

inline class CircleRadius(private val circleRadius : Double) : Drawable {
    val diameterOfCircle get() = 2 **  circleRadius
    fun areaOfCircle() = 3.14 **  circleRadius **  circleRadius

    override fun draw() {
        println("Draw my circle")
    }
}

6.結論

このクイック記事では、Kotlinのインラインクラスについて説明しました。さらに、継承、およびプロパティと関数の定義についても説明しました。

いつものように、これらの例とスニペットはすべてhttps://github.com/eugenp/tutorials/tree/master/core-kotlin[GitHubに載っています]にあります。