Scala案例类更新值

34

我有一个包含2个字符串成员的案例类。我想稍后更新第二个成员,所以我首先创建了一个带有String和None的实例,然后稍后加载数据到该类,并希望使用某些值来更新第二个成员。

我该怎么做?


你读过关于 case classes 的内容吗?你尝试写过一些代码吗? - vptheron
1
主要重复了 https://dev59.com/Cmw05IYBdhLWcg3wahRN 的内容。 - om-nom-nom
3个回答

83

定义 case class,使得第二个成员是 var

case class Stuff(name: String, var value: Option[String])

现在您可以创建Stuff的一个实例并修改第二个值:

val s = Stuff("bashan", None)

s.value = Some("hello")

然而,让case classes可变可能不是一个好主意。您应该更喜欢使用不可变的数据结构。而不是创建一个可变的case class,请将其变为不可变,并使用copy方法创建一个带有修改值的新实例。例如:

// Immutable Stuff
case class Stuff(name: String, value: Option[String])

val s1 = Stuff("bashan", None)

val s2 = s1.copy(value = Some("hello"))
// s2 is now: Stuff("bashan", Some("hello"))

18
在处理不可变的 case class 时,我发现引入一系列 withXYZ 方法对于最常见的修改值非常有用。例如,在 Stuff 类定义中加入 def withValue(v: String): Stuff = copy(value = Some(v)) 将允许您以以下方式创建一个已修改的副本:s1.withValue("hello") - Norbert Radyk
1
为什么不改变参数更可取?这是Scala特有的设计决策还是修改对象值更容易出错? - OfLettersAndNumbers
3
由于使对象不可变具有许多优点(即:创建后无法更改),因此这是有益的。它可以使代码更简单,防止并发问题(当多个线程正在访问一个对象时,如果一个线程在修改对象而同时其他线程也在使用这些对象,就会导致困难的问题)。这不是Scala特有的,但不可变性是函数式编程原则之一。 - Jesper
2
@ Jesper 感谢您的澄清。这很有道理。您如何知道何时使用不可变对象和可变对象?或者您可以仅考虑前者进行设计,而无需使用可变对象吗? - OfLettersAndNumbers
3
特别是如果你在以函数式编程的方式编写代码,那么理念是尽可能使事物不可变,但有时出于实用原因,你可能希望一些事物是可变的。你可以在网上找到大量关于可变与不可变的内容。Scala的case类主要是为了不可变而设计的。 - Jesper

3
假设您的案例类看起来像这样:
case class Data(str1: String, str2: Option[String]

首先,创建一个实例,并将第二个字符串设置为None

val d1 = Data("hello", None)

现在,您可以通过将此对象复制到一个新对象并替换str2的值来创建一个新值:

val d2 = d1.copy(str2=Some("I finally have a value here"))

我还会考虑一个可能性,那就是你的案例类可能不是你的数据的最佳表现形式。也许你需要一个类 DataWithStr2,它扩展了 Data,并添加了另一个始终被设置的字符串。或者也许你应该有两个没有关联的案例类,一个带有一个字符串,另一个带有两个字符串。


2

在Scala中,推荐使用不可变的Case类。如果您想要实现一个可变的类,请使用普通类,或者将您的Case类对象复制到一个新的对象中并更新值。


2
案例类并不总是不可变的。 - Jesper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接