2012-10-23 128 views
4

我想知道如何在Scala中使用.clone我自己的对象。在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) 
       ^

b。是否有办法在特征中声明拷贝构造函数(def this(o:A)),以便使用特征的类将被显示为需要提供一个特征。

c。说abstract trait有什么好处吗?

最后,有没有更好的方法,所有这一切的标准解决方案?

我已经研究过Java克隆。似乎不是为了这个。此外Scala copy不是 - 它只适用于case类,它们不应该有可变状态。

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

+2

如果你克隆状态_every time step_那么为什么“可变状态是必须的”?只有当你不需要每次都创建一个克隆时,可变性才是有效的。 –

回答

7

特征不能定义构造函数(我不认为abstract对特征有任何影响)。

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

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

+0

谢谢!看起来,自我类型不是必需的。 – akauppi

+2

没有必要,但会阻止你像'class Egg extends DeepCloneable [Potato]'一样进行类似的操作。 – Nick

3
  • 一个。当您在类型参数(如A)中定义后,在编译阶段后被清除。

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

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

  • b & c。 特征不能根据定义定义构造函数参数或辅助构造函数,它们也根据定义是抽象的。

    你可以做的是定义一个特征体能够顺利通过的具体实施实例称为

一个替代的解决方案是定义一个Cloneable类型类。有关这方面的更多信息,您可以找到关于此主题的大量博客,但我没有针对特定博客的建议。

scalaz有使用这种模式,也许你能找到灵感有巨大的一部分建:你可以看看OrderEqualShow得到它的要点。

+0

好,清楚的答案。特别感谢“a”的澄清。说得通。 – akauppi

2

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

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 = [email protected] 

scala> val y = x.copy 
y: Foo = [email protected] 

scala> x eq y 
res2: Boolean = false