在Scala中实现'.clone'

时间:2012-10-23 14:01:47

标签: scala

我正试图弄清楚如何在Scala中.clone我自己的对象。

这是一个模拟,所以可变状态是必须的,从而产生了克隆的全部需求。在向前移动模拟时间之前,我将克隆整个状态结构。

这是我目前的尝试:

abstract trait Cloneable[A] {
  // Seems we cannot declare the prototype of a copy constructor
  //protected def this(o: A)    // to be defined by the class itself

  def myClone= new A(this)
}

class S(var x: String) extends Cloneable[S] {
  def this(o:S)= this(o.x)    // for 'Cloneable'
  def toString= x
}

object TestX {
  val s1= new S("say, aaa")
  println( s1.myClone )
}

一个。为什么上面没有编译。给出:

error: class type required but A found
  def myClone= new A(this)
                   ^

湾有没有办法在特征中声明复制构造函数(def this(o:A)),以便显示使用特征的类需要提供一个。

℃。说abstract trait

有什么好处

最后,对于所有这些,有没有更好的标准解决方案?

我研究过Java克隆。似乎不适合这个。 Scala copy也不是 - 它只适用于案例类,它们不应该具有可变状态。

感谢您的帮助和任何意见。

3 个答案:

答案 0 :(得分:9)

Traits无法定义构造函数(我认为abstract对特征没有任何影响。)

是否有任何理由需要使用复制构造函数而不仅仅是实现克隆方法?有可能不必在类上声明[A]类型,但我至少声明了一个self类型,因此编译器将确保该类型与类匹配。

trait DeepCloneable[A] { self: A =>
    def deepClone: A
}

class Egg(size: Int) extends DeepCloneable[Egg] {
    def deepClone = new Egg(size)
}

object Main extends App {
    val e = new Egg(3)
    println(e)
    println(e.deepClone)
}

http://ideone.com/CS9HTW

答案 1 :(得分:3)

  • 一个。在编译阶段之后定义类型参数,例如A它会被删除

    这意味着编译器使用类型参数来检查您是否使用了正确的类型,但生成的字节码不保留A的信息。

    这也意味着您不能将A用作代码中的真实类,而只能用作“类型引用”,因为在运行时此信息会丢失。

  • b& C。 traits 不能按定义定义构造函数参数或辅助构造函数,它们也是定义抽象的。

    你可以做的是定义一个在实例化具体实现时调用的特质体

另一种解决方案是定义Cloneable 类型类。有关这方面的更多信息,你可以找到很多关于这个主题的博客,但我没有建议特定的博客。

scalaz使用此模式构建了一个巨大的部分,也许您可​​以在那里找到灵感:您可以查看OrderEqualShow以获取它

答案 2 :(得分:3)

它会建议基于类型的方法。有了这个,也可以让现有的类可以克隆:

class Foo(var x: Int)

trait Copyable[A] {
  def copy(a: A): A
}

implicit object FooCloneable extends Copyable[Foo] {
  def copy(foo: Foo) = new Foo(foo.x)
}

implicit def any2Copyable[A: Copyable](a: A) = new {
  def copy = implicitly[Copyable[A]].copy(a)
}


scala> val x = new Foo(2)
x: Foo = Foo@8d86328

scala> val y = x.copy
y: Foo = Foo@245e7588

scala> x eq y
res2: Boolean = false