使用case-classes进行可变状态是否(真的那么糟糕)?

时间:2015-09-24 19:05:09

标签: scala mutable case-class

请考虑以下代码:

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
  }
}

如您所见,case class保持可变状态。这样做非常气馁,通常我同意并坚持这个"规则",但这里讲的是整个故事。

我使用Scala从 scratch 编写一个小型3D游戏引擎。所以首先我考虑使用(更多)功能样式,但垃圾收集器会过于频繁。

考虑一下:我在测试游戏中有几十个实体。所有这些都有一个位置(Vector3),一个方向(Vector3),一个比例(Vector3)和一大堆矩阵。如果我要在这些类(Vector3和Matrix4)中运行并使它们不可变,我会每帧返回数百个新对象,导致巨大的fps损失,因为,让我们面对它,GC有它的用途,但在游戏引擎和OpenGL中......不是那么多。

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

那么,使用保持可变状态的案例类真的 是不是很糟糕?

将其转变为关于"为什么甚至将Scala用于这样的项目?"我知道那里可能是更好的选择,但我对用C ++编写(又一个)引擎不感兴趣,我也不急于潜入Rust(还)。 / p>

1 个答案:

答案 0 :(得分:5)

我会说使用具有可变状态的案例类是不好的,但这只是因为它们覆盖了let dict...equals方法。在代码的某处,您可以检查是否hashCode并发现它们是相同的。之后它们可能会有所不同,因为它们是可变的。至少,与基于散列的集合结合使用是很危险的。

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

怎么样:

toString