标记类型与类扩展AnyVal

时间:2017-10-14 18:39:53

标签: scala shapeless

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

示例:

trait CountryCodeTag
type CountryCode = String @@ CountryCodeTag

class CountryCode(code: String) extends AnyVal

2 个答案:

答案 0 :(得分:8)

<强> type CountryCode = String @@ CountryCodeTag

+ String @@ CountryCodeTagString的子类型,即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)

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

case class CountryCode(code: String) extends AnyVal
countryCode.copy(code = countryCode.code.toUpperCase)

+创建新值更自然:new CountryCode("a")

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

答案 1 :(得分:0)

这两种方法也有不同的性能特征。

标记类型与价值类相反,即使将其实例用作例如,也可以防止装箱。列表的元素。

https://failex.blogspot.nl/2017/04/the-high-cost-of-anyval-subclasses.html