我正试图弄清楚如何在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
也不是 - 它只适用于案例类,它们不应该具有可变状态。
感谢您的帮助和任何意见。
答案 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)
}
答案 1 :(得分:3)
一个。在编译阶段之后定义类型参数,例如A
它会被删除。
这意味着编译器使用类型参数来检查您是否使用了正确的类型,但生成的字节码不保留A
的信息。
这也意味着您不能将A
用作代码中的真实类,而只能用作“类型引用”,因为在运行时此信息会丢失。
b& C。 traits 不能按定义定义构造函数参数或辅助构造函数,它们也是定义抽象的。
你可以做的是定义一个在实例化具体实现时调用的特质体
另一种解决方案是定义Cloneable
类型类。有关这方面的更多信息,你可以找到很多关于这个主题的博客,但我没有建议特定的博客。
scalaz使用此模式构建了一个巨大的部分,也许您可以在那里找到灵感:您可以查看Order,Equal或Show以获取它
答案 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