为了引入更多类型安全性,我们可以使用shapeless
提供的标记类型,也可以创建扩展AnyVal
的类。使用一个而不是另一个有什么区别和优势/劣势?
示例:
trait CountryCodeTag
type CountryCode = String @@ CountryCodeTag
class CountryCode(code: String) extends AnyVal
答案 0 :(得分: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)
或
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