gpt4 book ai didi

scala - 创建(或复制)一个对象有多昂贵?

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

考虑这个简单的例子:

trait A { def a: String = "a"; def a2: String }
case class C(b: String, c: String) extends A {
val a2 = "a2"
}
val c = C("b", "")
val copy = c.copy(c="c")

当我用 .copy(c="c") 更新字段 c 时,其他字段(a,a2 b) 复制了吗?尽管只复制了它们的引用,但如果我有一个巨大的层次结构树,.copy 会变得非常昂贵吗?

类似地:

class Foo {
val list = List(1,2,3,4,5,6)
}
val foo1 = new Foo
val foo2 = new Foo

foo1foo2 共享一个 List 实例,或者每次我实例化一个 Foo 它都会创建一个新的 List?如果 listvar 而不是 val 会怎么样?

最佳答案

通常 Scala 是不可变的,您通常必须自己处理可变情况。此外,案例类本质上是不可变的,它们的复制方法由编译器生成。所以是的,他们将共享相同的对象引用。这是不可变性很好的原因之一。

你的第二个问题有点不同。在那种情况下,类是在单独的上下文中一个接一个地构造的。

检查正在编译的内容也是一个好主意:

>scalac -print test.scala

[[syntax trees at end of cleanup]] // test.scala
package test {
class Foo extends Object {
private[this] val list: List = _;
<stable> <accessor> def list(): List = Foo.this.list;
def <init>(): b.Foo = {
Foo.super.<init>();
Foo.this.list = immutable.this.List.apply(scala.this.Predef.wrapIntArray(Array[Int]{1, 2, 3, 4, 5, 6}));
()
}
}
}

由此可见,Scala 每次都会创建一个新的列表。将其更改为 var 不会改变任何内容,我们可以检查:

>scalac -print test.scala
[[syntax trees at end of cleanup]] // test.scala
package test {
class Foo extends Object {
private[this] var list: List = _;
<accessor> def list(): List = Foo.this.list;
<accessor> def list_=(x$1: List): Unit = Foo.this.list = x$1;
def <init>(): b.Foo = {
Foo.super.<init>();
Foo.this.list = immutable.this.List.apply(scala.this.Predef.wrapIntArray(Array[Int]{1, 2, 3, 4, 5, 6}));
()
}
}
}

它只为它生成了一个 setter 方法 (def list_=(x$1: List))。

如果您想在两种情况下都引用相同的列表,则使用对象的默认列表对其进行初始化:

object Foo {
val DefaultList = List(1,2,3,4,5,6)
}

class Foo {
var list = Foo.DefaultList
}

编译为以下内容:

>scalac -print test.scala
[[syntax trees at end of cleanup]] // test.scala
package test {
object Foo extends Object {
private[this] val DefaultList: List = _;
<stable> <accessor> def DefaultList(): List = Foo.this.DefaultList;
def <init>(): test.Foo.type = {
Foo.super.<init>();
Foo.this.DefaultList = immutable.this.List.apply(scala.this.Predef.wrapIntArray(Array[Int]{1, 2, 3, 4, 5, 6}));
()
}
};
class Foo extends Object {
private[this] var list: List = _;
<accessor> def list(): List = Foo.this.list;
<accessor> def list_=(x$1: List): Unit = Foo.this.list = x$1;
def <init>(): test.Foo = {
Foo.super.<init>();
Foo.this.list = Foo.DefaultList();
()
}
}
}

如您所见,列表只创建一次,然后通过 def DefaultList(): List 分配给每个 Foo 类实例化的引用。

关于scala - 创建(或复制)一个对象有多昂贵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20644898/

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