我希望有一个具有许多字段的类,如String,Boolean等,当构造类时,我希望有一个与每个字段关联的字段名并验证字段(使用正则表达式表示字符串)。理想情况下,我只想在构造函数中指定参数需要满足某些条件。
一些示例代码如何:
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伴侣对象的apply方法,但我希望有更通用的东西。
答案 0 :(得分:3)
在构造函数中放置逻辑(例如参数验证)是可疑的。从构造函数中抛出异常是双倍的。
通常这种创作模式最适合使用一种或多种工厂方法或某种类型的建造者。
对于基本工厂,只需使用所需的工厂方法定义随播广告。如果你想要相同的简写结构符号(new
- free),你可以重载预定义的apply
(尽管你可能不会替换其签名与case class
构造函数完全匹配的那个)。
如果您希望在验证失败时节省处理异常的客户代码,则可以返回Option[Data]
或Either[ErrorIndication, Data]
。或者你可以选择ScalaZ的Validation
,我将随意宣布超出这个答案的范围(因为我对它不够熟悉......)
但是,您不能拥有它们所呈现的属性不同的实例。甚至子类都不能从公共API中减去。如果您需要能够执行此操作,则需要更复杂的构造,例如trait
用于公共部分,而单独的case class
用于变体和/或扩展。