monolithic kernel

Kotlin で他のクラスを継承した data class の toString

August 09, 2021

Kotlin には、data class という機能がある。equalstoString などいくつかのメソッドを自動的に実装してくれるので、いわゆる値オブジェクトなんかを定義するのに便利な機能である。

ある日ふと思ったのが、親クラスで定義した toString を使い回せないかということ。というのも、他のクラスを継承して data class を定義した場合、親クラスで toString などのメソッドがどのように定義されていようとも、無視して強制的にデフォルト実装が自動的に定義されるようなのである。

答えとしてはドキュメントを読めば書いてあって、親クラスで final 修飾付きで定義しておけば、継承したときに自動的に上書きされることはなくなる。

// test.main.kts

data class DataClass(val value: Int)

abstract class SuperClass {
    override fun toString(): String {
        return "SuperClass"
    }
}

class DerivedClass(val value: Int) : SuperClass()

data class DerivedDataClass(val value: Int) : SuperClass()

abstract class SuperClassFinalToString {
    final override fun toString(): String {
        return "SuperClassFinalToString"
    }
}

data class DerivedDataClassFinalToString(val value: Int) : SuperClassFinalToString()

val data = DataClass(42)
val derived = DerivedClass(42)
val derivedData = DerivedDataClass(42)
val derivedDataFinalToString = DerivedDataClassFinalToString(42)

println("DataClass: $data") // => DataClass(value=42)
println("DerivedClass: $derived") // => SuperClass
println("DerivedDataClass: $derivedData") // => DerivedDataClass(value=42)
println("DerivedDataClassFinalToString: $derivedDataFinalToString") // => SuperClassFinalToString

その他の例も含めているので少し長くなっているが、DerivedDataClass が普通にやって toString が上書きされた例で、DerivedDataClassFinalToStringfinal をつけて上書きを防いだ例。

具体的な使いみちは考えてはいるものの、まだ試せていないので、うまくいったら別の機会で触れたい。