2

我想要一个具有多个字段的类,例如字符串、布尔值等,并且在构造该类时,我希望有一个与每个字段相关联的字段名并验证该字段(对字符串使用正则表达式)。理想情况下,我只想在构造函数中指定参数需要满足某些条件。

一些示例代码:

case class Data(val name: String ..., val fileName: String ...) {
  name.verify
  // Access fieldName associated with the name parameter.
  println(name.fieldName) // "Name"
  println(fileName.fieldName) // "File Name"
}

val x = Data("testName", "testFile")
// Treat name as if it was just a string field in Data
x.name // Is of type string, does not expose fieldName, etc

有没有一种优雅的方式来实现这一目标?

编辑:我认为我无法清楚地了解我所追求的。我有一个带有许多字符串参数的类。这些参数中的每一个都需要以特定方式进行验证,并且我还希望有一个与每个参数关联的字符串 fieldName。但是,我仍然希望能够将参数视为普通字符串(参见示例)。

我可以将逻辑编码到 Data 中,并作为每个参数的 Data 伴随对象的应用方法,但我希望有更通用的东西。

4

1 回答 1

3

将逻辑(例如参数验证)放入构造函数是可疑的。从构造函数中抛出异常是双重的。

通常这种创建模式最好使用一个或多个工厂方法或某种构建器。

对于基本工厂,只需定义一个带有您想要的工厂方法的伴侣。如果您想要相同的速记构造符号(new-free),您可以重载预定义的符号apply(尽管您可能不会替换其签名与case class构造函数完全匹配的符号)。

如果您想在验证失败时让您的客户端代码免于处理异常的混乱,您可以返回Option[Data]Either[ErrorIndication, Data]代替。或者你可以使用 ScalaZ's Validation,我将任意声明它超出了这个答案的范围(因为我对它不够熟悉......)

但是,您不能拥有在它们所呈现的属性上有所不同的实例。甚至子类也不能从公共 API 中减去。如果您需要能够做到这一点,您将需要更精细的构造,例如trait用于公共部分的 a 和case class用于变体和/或扩展的单独 es。

于 2013-02-14T00:12:59.417 回答