2012年11月2日金曜日

Scala Tips / case classのcopy constructor

ちょっと旧聞になりますがScala 2.8(2009年)で導入されたNamed and Default Argumentsは地味ですが非常にインパクトのある機能でした。Named and Default Argumentsと同時にCompiler-generated copy methods、いわゆるcopy constructorも導入されました。

これらの機能の導入によってcase classの価値が大幅に向上したといえます。

たとえば、以下のcase class Personがあるとします。これは何の変哲もないcase classですね。

scala> case class Person(name: String, age: Int, phone: String)
defined class Person

Personのインスタンスは以下のように生成します。

scala> val a = Person("Taro", 30, "123-456-7890")
a: Person = Person(Taro,30,123-456-7890)

さて、このPersonの年令を30から35に変更するとします。Personの実装は不変オブジェクトなので値を直接変更することはできないので、値を変更した新しいオブジェクトを再作成します。

普通に考えるとこの処理は以下のようになります。この方法の問題点は、case classの定義する変数をすべて並べて再設定しなければならないことです。この例では、変数の数が3つなのでたいしたことはありませんが、実際のプログラムでは10個ぐらい並ぶのはざらなのですし、データベースのレコードを引き写したcase classだと100個(100カラム)になるかもしれません。こうなってくるとプログラミング時に手で記述していくのは苦行になってしまいます。

scala> val b = Person(a.name, 35, a.phone)
b: Person = Person(Taro,30,123-456-7890)

そこで登場するのがcase classに自動的に追加されるcopyメソッドです。

以下のように値を変更するパラメタのみを指定してcopyメソッドを呼び出すと、指定された値が更新された新しいcase classインスタンスを得ることができます。

scala> val b = a.copy(age = 35)
b: Person = Person(Taro,35,123-456-7890)

copyメソッドを使うことで、不変オブジェクトの一部を更新する永続データ構造系のテクニックをcase classで簡単に使えるようになります。

このあたりのテクニックについて、以前書いたものを調べてみたら、今回の内容とかなり近しいものが見つかりました。視点がちょっと違うのでよしとしましょう。

諸元

  • Scala 2.10.0-RC1

0 件のコメント:

コメントを投稿