ScalaObjectCloning

Java言語で学ぶデザインパターン入門 の第6章 Prototype を Scala で書き直してみて、オブジェクトのクローニングでちょっとつまづいたのでメモ。

結論を先に言うと、オブジェクトのクローニングしたい場合には、クラスやトレイトの宣言時に、@cloneable アノテーションを入れると OK。

@cloneable class Hoge {
  ...
}

以下、つまづいて調べた経緯。元書籍での Product クラスは以下のように、Cloneable を継承している。

#!java
package framework;

public interface Product extends Cloneable {
    public abstract void use(String s);
    public abstract Product createClone(); 
}

で、Scala でのクローニングについて、「Scala cloneable」でググると、一番上に出てきた http://www.scala-lang.org/node/110 では、以下のようなコードが載っていた。

trait Cloneable extends java.lang.Cloneable {
  override def clone(): Cloneable = { super.clone(); this }
}
trait Resetable {
  def reset: Unit
}

これを参考にして、Product クラスを Scala で以下のように書き直してみた。

package framework

trait Product extends java.lang.Cloneable {
  def use(s: String): Unit
  def createClone(): Product
  override def clone(): Cloneable = { super.clone(); this }
}

これでとりあえずは動いたんだけど、いまいちスッキリしない。そもそも Scala は Java だけではなく、.NET でも動くということなんだけど、java.lang.Cloneable を継承してると、Java でしか動かなくてイマイチ。(まあ、習作用コードでそこまで気にする必要もないんだけど。)

というわけで調べてみたら、@cloneable アノテーションを使えばいいみたい。

package framework

@cloneable trait Product {
  def use(s: String): Unit
  def createClone(): Product
}

これで意図通りに動いた。

@cloneable を頭に入れないと、実行時に CloneNotSupportedException が発生する。