【问题标题】:Type aliasing a case class in Scala 2.10在 Scala 2.10 中为案例类键入别名
【发布时间】:2014-02-17 14:21:05
【问题描述】:

我使用的是 Scala 2.10.2,并且有两个具有相同字段的案例类:

case class Foo(id: String, name: String)
case class Bar(id: String, name: String)

我想做这样的事情:

case class Thing(id: String, name: String)
type Foo = Thing
type Bar = Thing

这可以编译,但是当我尝试创建 Foo 时,我得到:

scala> Bar("a", "b")
<console>:8: error: not found: value Bar
              Bar("a", "b")
              ^

类型别名是否不适用于案例类?

【问题讨论】:

    标签: scala


    【解决方案1】:

    当你创建一个案例类时,Scala 会自动为它创建一个伴生对象。在您的代码中,您为Thing 类型定义了一个别名,即仅为Thing 类定义一个别名。您的伴生对象 Thing 仍然只有 1 个名称且没有别名。

    “修复”它的一种方法是创建对伴随对象(不是类型别名)的引用,如下所示:

    scala> val Bar = Thing
    Bar: Thing.type = Thing
    
    scala> Bar("a", "b")
    res1: Thing = Thing(a,b)
    

    另一种“修复”它的方法是将导入的对象重命名为import package.{Thing =&gt; Bar}

    【讨论】:

    • val Bar = Thing 这将添加一个对象别名而不是类型别名
    • @AlekseyIzmailov 我仍然会说“创建对伴随对象的引用类型别名一起”。
    【解决方案2】:

    类型别名只是类型的别名,而不是任何可能提供工厂方法的伴随对象(无论您是自己编写工厂方法还是从编译器“免费”获得一个)。

    另一方面,导入作用于名称,如果有多个实体与给定名称相关联,则导入该名称会引入导入名称的每个引用对象。此外,您可以在导入时重命名,并且可以乘以重命名,所以...

    scala> object Stuff { case class Thing(id: String, name: String) }
    defined module Stuff
    
    
    scala> import Stuff.Thing
    import Stuff.Thing
    
    scala> import Stuff.{Thing => Foo}
    import Stuff.{Thing=>Foo}
    
    scala> import Stuff.{Thing => Bar}
    import Stuff.{Thing=>Bar}
    
    
    scala> val thing1 = Thing("fing", "fang")
    thing1: Stuff.Thing = Thing(fing,fang)
    
    scala> val foo1 = Foo("yes", "no")
    foo1: Stuff.Thing = Thing(yes,no)
    
    scala> val bar1 = Bar("true", "false")
    bar1: Stuff.Thing = Thing(true,false)
    

    不过,正如您所见,通过toString 进行渲染并不好。

    【讨论】:

      【解决方案3】:
      case class Thing(id: String, name: String)
      type Foo = Thing
      type Bar = Thing
      

      如果你说new Bar("a","b") 它会起作用

      【讨论】:

        【解决方案4】:

        您是否希望 FooBar 可区分(当它们是不同的案例类时)?如果是,并且您只是想避免重复的字段列表,您可以这样做:

        case class Foo(thing: Thing)
        case class Bar(thing: Thing)
        

        但这显然会使它们在模式匹配或访问字段中使用起来不太方便。字段访问可以改进一点:

        trait ThingWrapper {
          def thing: Thing
          def id = thing.id
          def name = thing.name
        }
        
        case class Foo(thing: Thing) extends ThingWrapper
        case class Bar(thing: Thing) extends ThingWrapper
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-02-17
          • 1970-01-01
          • 2019-03-22
          • 2021-10-25
          • 2011-06-17
          • 2013-04-11
          • 1970-01-01
          相关资源
          最近更新 更多