如何深度复制混有特征的类

2024-04-12

这是一些示例 scala 代码。

abstract class A(val x: Any) {  
    abstract def copy(): A  
}  

class b(i: Int) extends A(i) {  
    override def copy() = new B(x)  
}  

class C(s: String) extends A(s) {  
    override def copy() = new C(x)  
}  

//here's the tricky part  
Trait t1 extends A {  
    var printCount = 0  

    def print = {  
        printCount = printCount + 1  
        println(x)  
    }  

    override def copy = ???  
}  

Trait t2 extends A {  
    var doubleCount = 0  

    def doubleIt = {  
        doubleCount = doubleCount + 1  
        x = x+x  
    }  

    override def copy = ???  
}  

val q1 = new C with T1 with T2  
val q2 = new B with T2 with T1  

好的,正如您可能已经猜到的,问题是这样的。 如何在 T1 和 T2 中实现复制方法,以便将它们与 B、C 或 t2/t1 混合在一起,我可以获得整个蜡球的副本? 例如,q2.copy应该返回一个新的B,T2和T1,而q1.copy应该返回一个新的C,T1和T2

Thanks!


对象构造的组合性

The basic problem here is, that, in Scala as well as in all other languages I know, object construction doesn't compose. Consider two abstract operations op1 and op2, where op1 makes property p1 true and where op2 makes property p2 true. These operations are composable with respect to a composition operation ○, if op1 ○ op2 makes both p1 and p2 true. (Simplified, properties also need a composition operation, for example conjunction such as and.)

让我们考虑一下new操作和财产new A(): A,即通过调用创建的对象new A属于类型A. The new操作缺乏组合性,因为没有操作/语句/函数f在 Scala 中,您可以编写new A and new B这样f(new A, new B): A with B。 (简单来说,不用想太多A and B必须是类、特征、接口或其他)。

使用超级调用进行组合

超级调用通常可用于组合操作。考虑以下示例:

abstract class A { def op() {} }

class X extends A {
  var x: Int = 0
  override def op() { x += 1 }
}

trait T extends A {
  var y: String = "y"
  override def op() { super.op(); y += "y" }
}

val xt = new X with T
println(s"${xt.x}, ${xt.y}") // 0, y
xt.op()
println(s"${xt.x}, ${xt.y}") // 1, yy

Let X.op的属性为“x增加一”并让T.op的属性为“y的长度增加了 1”。通过超级调用实现的构图满足了这两个属性。万岁!

你的问题

假设您正在与一个班级一起工作A其中有一个字段x, 一个特质T1其中有一个字段y还有另一个特点T2其中有一个字段z。您想要的是以下内容:

val obj: A with T1 with T2
// update obj's fields
val objC: A with T1 with T2 = obj.copy()
assert(obj.x == objC.x && obj.y == objC.y && obj.z == objC.z)

您的问题可以分为两个与组合性相关的子问题:

  1. Create所需类型的新实例。这应该通过以下方式实现:construct method.

  2. 初始化新创建的对象,使其所有字段都具有与源对象相同的值(为简洁起见,我们只使用值类型字段,而不使用引用类型字段)。这应该通过以下方式实现:initialise method.

第二个问题可以通过超级调用解决,第一个问题不能。我们将首先考虑更简单的问题(第二个)。

对象初始化

我们假设construct方法按需要工作并产生正确类型的对象。类似于op我们可以实现初始示例中的方法initialise这样每个类别/特征A, T1 and T2实施initialise(objC)通过将其了解的字段设置为相应的值this(个人效果),并通过调用super.initialise(objC)为了合成这些单独的效果。

对象创建

据我所知,没有办法组合对象创建。如果一个实例A with T1 with T2是要创建的,那么语句new A with T1 with T2必须在某个地方执行。如果超级调用可以在这里提供帮助,那么类似

val a: A = new A // corresponds to the "deepest" super-call
val at1: A with T1 = a with new T1

将是必要的。

可能的解决方案

我实施了一个解决方案(看到这个要点 https://gist.github.com/anonymous/5037918)基于抽象类型成员和显式混合类(class AWithT1WithT2 extends A with T1 with T2; val a = new AWithT1WithT2代替val a = new A with T1 with T2)。它可以工作并且类型安全,但它既不是特别好也不是简洁。显式 mixin 类是必要的,因为construct的方法new A with T1 with T2必须能够命名它创建的类型。

其他类型安全性较低的解决方案可能也是可能的,例如,通过铸造asInstanceOf或反思。不过,我还没有尝试过类似的事情。

Scala 宏也可能是一种选择,但我还没有使用过它们,因此对它们了解不够。编译器插件可能是另一个重量级选项。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何深度复制混有特征的类 的相关文章

随机推荐