Kotlinのインラインクラス

Kotlinのインラインクラス

1. 概要

Kotlin 1.3以降には、inline classと呼ばれる実験的な新しいタイプのクラスがあります。 このチュートリアルでは、インラインクラスの使用法とその制限のいくつかに焦点を当てます。

2. セットアップ

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

この警告を回避するために、次のMaven compiler optionを構成に追加できます。


    
        -XXLanguage:+InlineClasses
    

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

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

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

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

val circleRadius = InlinedCircleRadius(5.5)

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

val circleRadius = 5.5

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

3.1. 使用例

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

A single property initialized in the primary constructor is the basic requirement of aninline class.単一のプロパティは、実行時にクラスインスタンスを表します。

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

inline class InlineDoubleWrapper(val doubleValue : Double)

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

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

4. クラスメンバー

これまで、単純なラッパーのようにインラインクラスを使用していました。 しかし、彼らはそれ以上のものです。 They also allow us to define properties and functions just like regular classes.この次の例では、直径を表すプロパティと、円の面積を返す関数を定義します。

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())
}

ただし、インラインクラス内で定義できるものとできないものにはいくつかの制限があります。 While properties and functions are allowed, we have to mention that init blocks, inner classes, and backing fields are not.

5. 継承

inline classes can inherit only from interfacesに言及することが重要です。サブクラスを作成できないため、inline classes are also effectively final.

メソッド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のインラインクラスについて説明しました。 さらに、継承とプロパティと関数の定義についても話しました。

いつものように、これらの例とスニペットはすべてover on GitHubにあります。