标记类型与类扩展AnyVal

gyo*_*oho 7 scala shapeless

为了引入更多的类型安全性,我们既可以使用提供的标记类型,也可以shapeless创建一个扩展的类AnyVal.使用一个而不是另一个有什么区别和优势/劣势?

例:

trait CountryCodeTag
type CountryCode = String @@ CountryCodeTag

class CountryCode(code: String) extends AnyVal
Run Code Online (Sandbox Code Playgroud)

Dmy*_*tin 8

type CountryCode = String @@ CountryCodeTag

+ String @@ CountryCodeTag是一个子类型String,即所有方法String都可以直接使用:countryCode.toUpperCase.

- String @@ CountryCodeTag可以在某些String预期的地方意外使用,即它的类型安全性较低.

- 创造新价值有点尴尬:"a".asInstanceOf[String @@ CountryCodeTag]val tagger = new Tagger[CountryCodeTag]; tagger("a").

- 对Shapeless的依赖(虽然这可以手动完成).

class CountryCode(code: String) extends AnyVal

+它更安全.

- String可以通过一些额外的努力获得方法:

class CountryCode(val code: String) extends AnyVal
new CountryCode(countryCode.code.toUpperCase)
Run Code Online (Sandbox Code Playgroud)

要么

class CountryCode(val code: String) extends AnyVal 
object CountryCode {
  def unapply(...) = ...
}
countryCode match { case CountryCode(code) => new CountryCode(code.toUpperCase) }
Run Code Online (Sandbox Code Playgroud)

要么

case class CountryCode(code: String) extends AnyVal
countryCode.copy(code = countryCode.code.toUpperCase)
Run Code Online (Sandbox Code Playgroud)

+创造新价值更自然:new CountryCode("a").

+没有额外的依赖(它是普通的Scala).

  • @gyoho注意到很多情况下需要实例化anyval类,从而失去运行时的好处. (2认同)