用于类型安全的单元件案例类
为了实现类型安全,有时我们希望避免在我们的域上使用原始类型。例如,想象一个带有 name
的 Person
。通常,我们会将 name
编码为 String
。但是,将表示 Person
的 name
的 String
与表示错误消息的 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)
如果我们将 PersonName
与 ErrorMessage
,甚至普通的 String
混合,我们的代码将无法编译。
val maybeName: Either[ErrorMessage, PersonName] = ???
maybeName.foreach(reportError) // ERROR: tried to pass PersonName; ErrorMessage expected
maybeName.swap.foreach(reportError) // OK
但是这会产生很小的运行时间开销,因为我们现在必须将 String
s 装入/取出 String
容器。为了避免这种情况,可以制作 PersonName
和 ErrorMessage
值类:
case class PersonName(val value: String) extends AnyVal
case class ErrorMessage(val value: String) extends AnyVal