KisaragiEffective.github.io

Yeet.

View on GitHub

ミュータブル=死亡の世界

考察

なぜ人はイミュータブルなオブジェクトを好むのか?

Make it immutable in Kotlin

A1: data class と val のあわせ技

data class Person(val age: Int, val address: StructedAddress)

シンプル・イズ・ベストという言葉通りである。暗黙のうちに、指定されたパラメーターのみ変化させた新しいインスタンスを生成するcopy()関数と、宣言順でタプルのように分解宣言をすることができるcomponentN()が定義される。さらに、equals()hashCode()も暗黙のうちに生成されるといたれりつくせりである。 (もちろん、明白に定義されていればそちらを優先する)

A2: ミュータブルなオブジェクトを包み直す

class ImmutablePerson(private val delegate: MutablePerson): IPerson {
  fun setAge(v: Int) {
    unsupported()
  }

  fun getAge(): Int {
    return delegate.age
  }

  fun setAddress(v: StructedAddress) {
    unsupported()
  }

  fun getAddress(): StructedAddress {
    return delegate.address
  }
  
  fun unsupported(): Nothing {
    throw UnsupportedOperationException("Cannot call mutable method")
  }
}

委譲 というテクニックで、継承よりも良いとされている。具体的には、万が一MutablePersonfinalになったとしても、コードの変更が不要という点だ。

A3: 継承してしまう

class ImmutablePerson(age: Int, address: StructedAddress) : MutablePerson(age, address) {
  override fun setAge(v: Int) {
    unsupported()
  }

  override fun getAge(): Int {
    return super.age
  }

  override fun setAddress(v: StructedAddress) {
    unsupported()
  }

  override fun getAddress(): StructedAddress {
    return super.address
  }
  
  fun unsupported(): Nothing {
    throw UnsupportedOperationException("Cannot call mutable method")
  }
}