用于类型安全的单元件案例类

为了实现类型安全,有时我们希望避免在我们的域上使用原始类型。例如,想象一个带有 namePerson。通常,我们会将 name 编码为 String。但是,将表示 PersonnameString 与表示错误消息的 String 混合起来并不困难:

def logError(message: ErrorMessage): Unit = ???
case class Person(name: String)
val maybeName: Either[String, String] = ??? // Left is error, Right is name
maybeName.foreach(logError) // But that won't stop me from logging the name as an error!

为了避免这些陷阱,你可以对数据进行编码,如下所示:

case class PersonName(value: String)
case class ErrorMessage(value: String)
case class Person(name: PersonName)

如果我们将 PersonNameErrorMessage,甚至普通的 String 混合,我们的代码将无法编译。

val maybeName: Either[ErrorMessage, PersonName] = ???
maybeName.foreach(reportError) // ERROR: tried to pass PersonName; ErrorMessage expected
maybeName.swap.foreach(reportError) // OK

但是这会产生很小的运行时间开销,因为我们现在必须将 Strings 装入/取出 String 容器。为了避免这种情况,可以制作 PersonNameErrorMessage 值类:

case class PersonName(val value: String) extends AnyVal
case class ErrorMessage(val value: String) extends AnyVal