gpt4 book ai didi

scala - 如何深度复制混合了特征的类

转载 作者:行者123 更新时间:2023-12-01 12:46:49 24 4
gpt4 key购买 nike

这是一些示例 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 应该返回一个带有 T2 和 T1 的新 B,而 q1.copy 应该返回一个带有 T1 和 T2 的新 C

谢谢!

最佳答案

对象构造的组合性

这里的基本问题是,在 Scala 以及我所知道的所有其他语言中,对象构造不组合。考虑两个抽象操作 op1 和 op2,其中 op1 使属性 p1 为真,其中 op2 使属性 p2 为真。如果 op1 ○ op2 使 p1 和 p2 都为真,则这些操作相对于组合操作 ○ 是可组合的。 (简而言之,属性也需要组合操作,例如和等连词。)

让我们考虑 new new A(): A 的操作和属性,即调用new A创建的对象是 A 类型. new操作缺乏组合性,因为没有操作/语句/函数f在 Scala 中,您可以编写 new Anew B这样f(new A, new B): A with B . (简而言之,不要想太多 AB 是否必须是类或特征或接口(interface)或其他)。

使用 super 调用组合

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

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

X.op的属性为“ x 加一”并令 T.op的属性为“ y 的长度加一”。用 super 调用实现的组合满足这两个特性。万岁!

你的问题

假设您正在使用一个类 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)

您的问题可以分为两个与组合性相关的子问题:
  • 创建所需类型的新实例。这应该通过 construct 来实现方法。
  • 初始化新创建的对象,使其所有字段都具有与源对象相同的值(为简洁起见,我们将只使用值类型的字段,而不是引用类型的字段)。这应该通过 initialise 来实现方法。

  • 第二个问题可以通过 super 调用解决,第一个不能。我们将首先考虑更容易的问题(第二个)。

    对象初始化

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

    对象创建

    据我所知,没有办法组合对象创建。如果 A with T1 with T2 的实例将被创建,然后语句 new A with T1 with T2必须在某处执行。如果 super 电话在这里可以提供帮助,那么类似
    val a: A = new A // corresponds to the "deepest" super-call
    val at1: A with T1 = a with new T1

    将是必要的。

    可能的解决方案

    我实现了一个基于抽象类型成员和显式混合类( class AWithT1WithT2 extends A with T1 with T2; val a = new AWithT1WithT2 而不是 val a = new A with T1 with T2 )的解决方案( see this gist )。它可以工作并且是类型安全的,但它既不是特别好也不简洁。显式混合类是必要的,因为 construct new A with T1 with T2的方法必须能够命名它创建的类型。

    其他类型安全性较低的解决方案可能是可能的,例如,通过 asInstanceOf 进行转换或反射(reflection)。不过,我还没有尝试过类似的方法。

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

    关于scala - 如何深度复制混合了特征的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15079444/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com