【问题标题】:Pre-process parameters of a case class constructor without repeating the argument list案例类构造函数的预处理参数而不重复参数列表
【发布时间】:2014-09-16 11:42:58
【问题描述】:

我有这个带有很多参数的案例类:

case class Document(id:String, title:String, ...12 more params.. , keywords: Seq[String]) 

对于某些参数,我需要在创建对象之前进行一些字符串清理(修剪等)。

我知道我可以添加一个带有 apply 函数的伴随对象,但我想要的最后一件事是在我的代码中编写参数列表 TWICE(案例类构造函数和伴随对象的应用)。

Scala 是否提供任何帮助我解决此问题?

【问题讨论】:

  • 并非如此,因为它有点违背案例类的概念。一个普通的类构造函数或覆盖apply 必须这样做。
  • 使用Builder 模式

标签: scala


【解决方案1】:

我的一般建议是:

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

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

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

case class Document(id: String, title: String, keywords: Seq[String], preprocessed: Boolean = false) {
  def preprocess() = if (preprocessed) this else {
    this.copy(title = title.trim, preprocessed = true) // or whatever you want to do
  }
}

但是:您不能阻止客户端将preprocessed 初始化为true

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

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

但是:模式匹配和默认的 toString 实现不会给你想要的东西......

【讨论】:

  • 有趣的方法:保持 Document 不可变,但在构造函数的污染方面不足。
  • private val _keyword 解决方案很丑,但效果很好。 toString 在我的测试中表现良好。你有什么问题?另外:我的自动 JSON 序列化程序很高兴地忽略了“_keyword”,所以我准备好了。谢谢!
  • @sscarduzio:toString 实现使用(未预处理的)_keywords 成员,而不是预处理的 keywords。那就是行为显然没问题(案例类对keywords getter 一无所知),但它可能会造成混乱。
【解决方案2】:

换了半个小时的上下文后,我用新的眼光看待这个问题,想到了这个:

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

我只是在类主体中添加var 和清理数据使参数可变。

好的,我知道,我的数据不再是不可变的,Martin Odersky 可能会在看到这个后杀死一只小猫,但是嘿.. 我设法做我想做的事,添加 3 个字符。我称之为胜利:)

【讨论】:

  • 我没想到你会这么轻易地放弃不变性:)。仍有希望使其成为 val - 请参阅我的更新答案...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 2015-05-16
  • 1970-01-01
相关资源
最近更新 更多