【问题标题】:Tagged Type vs class extends AnyVal标记类型与类扩展 AnyVal
【发布时间】:2018-04-02 22:36:47
【问题描述】:

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

例子:

trait CountryCodeTag
type CountryCode = String @@ CountryCodeTag

class CountryCode(code: String) extends AnyVal

【问题讨论】:

    标签: scala shapeless


    【解决方案1】:

    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)。

    【讨论】:

    • 你能给我举个缺点的例子吗:String @@ CountryCodeTag can be accidentally used where some String is expected?
    • @gyoho val countryCode: String @@ CountryCodeTag = ??? case class Person(name: String) Person(countryCode)
    • 从内存占用的角度来看,你认为哪一个效果更好?
    • 在运行时,CountryCodes 都只是 Strings (使用方法 extracted 到伴随对象)所以我想应该没有任何区别。
    • @gyoho 请注意,在很多情况下需要实例化 anyval 类,从而失去其运行时优势。
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2013-02-02
      • 1970-01-01
      • 1970-01-01
      • 2015-11-06
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多