gpt4 book ai didi

scala - 将案例类用于可变状态是否(真的)不好?

转载 作者:行者123 更新时间:2023-12-01 11:30:16 29 4
gpt4 key购买 nike

考虑以下代码:

case class Vector3(var x: Float, var y: Float, var z: Float)
{
def add(v: Vector3): Unit =
{
this.x += v.x
this.y += v.y
this.z += v.z
}
}

如您所见,案例类 拥有可变状态。非常不鼓励这样做,通常我会同意并绝对遵守这个“规则”,但这是整个故事。

我正在使用 Scala 从 scratch 编写一个小的 3d 游戏引擎。所以首先我考虑使用(更多)函数式风格,但是垃圾收集器会经常启动。

想一想:我在一个测试游戏中有几十个实体。它们都有一个位置 (Vector3)、一个方向 (Vector3)、一个比例 (Vector3) 和一大堆矩阵。如果我要在这些类(Vector3 和 Matrix4)中发挥作用并使它们不可变,我将每帧返回数百个新对象,从而导致巨大的 fps 损失,因为让我们面对现实吧,GC 有其用途,但在游戏引擎和 OpenGL……没那么多。

Vector3 以前是一个类,但现在是一个案例类,因为在代码的某处我需要对其进行模式匹配。

那么,使用包含可变状态的案例类真的那么不好吗?

不要把它变成关于“你为什么还要在这样的项目中使用 Scala?”的讨论。我知道那里可能有更好的选择,但我对用 C++ 编写(又一个)引擎不感兴趣,我也不太急于钻研 Rust(目前)。

最佳答案

我会说使用具有可变状态的案例类是不好的,但这只是因为它们会覆盖您的 equalshashCode 方法。在您的代码中的某处,您可能会检查 a == b 并发现它们是否相等。后来它们可能会有所不同,因为它们是可变的。至少,将它们与基于散列的集合结合使用是危险的。

但是,您似乎并不需要案例类提供的所有功能。您真正需要的似乎是用于模式匹配的提取器,那么为什么不定义它呢?此外,静态工厂 apply 和可读的 toString 表示可能很方便,因此您可以实现它们。

怎么样:

class Vector (var x: Float, var y: Float, var z: Float) {
override def toString = s"Vector($x, $y, $z)"
}

object Vector {
def apply(x: Float, y: Float, z: Float) = new Vector(x, y, z)

def unapply(v: Vector): Option[(Float, Float, Float)] = Some((v.x, v.y, v.z))
}

关于scala - 将案例类用于可变状态是否(真的)不好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32769021/

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