Scala 在不重复参数列表的情况下预处理案例类构造函数的参数

Scala 在不重复参数列表的情况下预处理案例类构造函数的参数,scala,Scala,我有一个案例类,有很多参数: case class Document(id:String, title:String, ...12 more params.. , keywords: Seq[String]) 对于某些参数,我需要在创建对象之前进行一些字符串清理(修剪等) 我知道我可以添加一个带有apply函数的伴生对象,但我最不想做的就是在代码中编写两次参数列表(case类构造函数和伴生对象的apply) Scala在这方面有什么帮助吗?我的一般建议是: 您的目标(数据预处理)是伴生对象

我有一个案例类,有很多参数:

case class Document(id:String, title:String, ...12 more params.. , keywords: Seq[String]) 
对于某些参数,我需要在创建对象之前进行一些字符串清理(修剪等)

我知道我可以添加一个带有apply函数的伴生对象,但我最不想做的就是在代码中编写两次参数列表(case类构造函数和伴生对象的apply)


Scala在这方面有什么帮助吗?

我的一般建议是:

  • 您的目标(数据预处理)是伴生对象的完美用例——因此,尽管有样板,它可能是最惯用的解决方案

  • 如果case类参数的数量很大,那么builder模式肯定会有所帮助,因为您不必记住参数的顺序,并且您的IDE可以帮助您调用builder成员函数。为case类构造函数使用命名参数也允许使用随机参数顺序,但据我所知,命名参数没有IDE自动完成=>使构建器类稍微方便一些。然而,使用构建器类会引发如何处理强制指定某些参数的问题——简单的解决方案可能会导致运行时错误;这篇文章有点冗长。在这方面,带有默认参数的case类更优雅

还有一种解决方案:引入一个附加标志
preprocessed
,默认参数为
false
。每当您想要使用实例
val d:Document
,您都可以调用通过case类copy方法实现的
d.preprocess()
(以避免再次键入所有参数):

但是:您不能阻止客户端初始化
预处理
设置为
true

另一个选项是将一些参数设置为
private val
,并为预处理的数据公开相应的getter:

case class Document(id: String, title: String, private val _keywords: Seq[String]) {
  val keywords = _keywords.map(kw => kw.trim)
}

但是:模式匹配和默认的
toString
实现并不能完全满足您的需求…

在更改上下文半小时后,我以全新的眼光看待这个问题,并提出了以下建议:

case class Document(id: String, title: String, var keywords: Seq[String]) {
  keywords = keywords.map(kw => kw.trim)
}
我只需在类主体中添加
var
和清理数据,即可使参数可变


好吧,我知道,我的数据不再是一成不变的,马丁·奥德斯基可能会在看到这一点后杀死一只小猫,但是嘿。。我成功地完成了我想添加的3个字符。我称之为胜利:)

不太可能,因为这有点违背了案例类的概念。一个普通的类构造函数或重写
apply
将不得不这样做。使用有趣的方法:保持文档不变,但在构造函数的污染方面有所欠缺。
private val\u关键字
解决方案很难看,但效果非常好。toString在我的测试中表现良好。你有什么问题?另外:我的自动JSON序列化程序很高兴地忽略了“_关键字”,所以我已经准备好了。谢谢@sscarduzio:
toString
实现使用(未处理的)
\u关键字
成员,而不是预处理的
关键字
。这就是行为显然是可以的(case类对
关键字
getter一无所知),但它可能会造成混淆。我没想到您会那么容易地放弃不变性:)。仍然有希望使其成为val--请参阅我更新的答案。。。
case class Document(id: String, title: String, var keywords: Seq[String]) {
  keywords = keywords.map(kw => kw.trim)
}