【问题标题】:Extending a trait and types扩展特征和类型
【发布时间】:2010-11-29 11:01:29
【问题描述】:

我想要一个密封的特征,它有一个声明的方法,它返回 扩展特征的实际类。我应该使用抽象类型、参数类型还是 有没有其他好的方法来解决这个问题?

sealed trait Foo {
  type T
  def doit(other: T): T
}

sealed trait Foo[T] {
  def doit(other: T): T
}

请注意,T 在此示例中必须是 Foo 的子类型。如果我这样做,类型 信息感觉过于重复:

case class Bar(name: String) extends Foo[Bar] {
  def doit(other: Bar): Bar = ...
}

【问题讨论】:

    标签: scala


    【解决方案1】:

    它们大多是可以互换的。根据 Odersky 的说法,原因主要是为了完整性:类似于方法和字段(值)可以是抽象的或作为参数传递的事实,类型也可以。

    当您打算混合使用相同类型名称的多个特征时,最好使用抽象类型。使用类型参数,您需要将类型显式传递给每个

    这是一篇解释所有这些的文章:http://www.artima.com/weblogs/viewpost.jsp?thread=270195

    【讨论】:

      【解决方案2】:

      您可以通过让您的 doit 方法返回一个工厂函数来减少重复:

      trait Foo[T] { 
         self: T =>
         def doit: T => T 
      }
      
      case class Bar(name: String) extends Foo[Bar] {
         // note: types omitted 
         def doit = { other => Bar(name + other.name) }
      }
      

      不可能对抽象类型做同样的事情:

      trait Foo { 
         self: T => // won't compile because T isn't defined yet
         type T 
         def doit: T => T
      }
      

      【讨论】:

        【解决方案3】:

        你可以写:

        trait Foo[T] {
          self:T =>
          def doit(other: T): T
        }
        
        case class Bar(name: String) extends Foo[Bar] {
          def doit(other: Bar): Bar = ...
        }
        

        与您的示例不同的是 Bar 不能以任何其他方式实例化(例如 case class Bar(name: String) extends Foo[String])。

        【讨论】:

          【解决方案4】:
          trait Foo[A <: Foo[A]]
          

          只有当 A 是 Foo[A] 的子类型并且唯一满足的类型是类 Foo 被混合时,才能混合这个特征。我在 Lift 的 Mapper 特征中看到了这个解决方案。

          【讨论】:

          • 不完全。试试class Bar extends Foo[Bar]class Baz extends Foo[Bar]
          【解决方案5】:

          编辑 - 以下是我的原始答案。您的评论表明您希望返回匹配类型的任意实例,但我并不认为这是明智的。 假设是,通过T.type 语法

          trait T { def foo : T.type }
          
          trait U extends T { def foo = new U } //must be a U
          
          class W extends U
          
          val w : W = (new W).foo //oh dear.
          

          这可以通过this.type来完成:

          scala> trait T {
           | def foo : this.type
           | }
          defined trait T
          
          scala> class W extends T {
           | def foo  = this
           | }
          defined class W
          
          scala> (new W).foo
          res0: W = W@22652552
          
          scala> res0.foo
          res1: res0.type = W@22652552
          

          还有:

          scala> ((new W) : T)
          res4: T = W@45ea414e
          
          scala> res4.foo.foo.foo
          res5: res4.type = W@45ea414e
          

          【讨论】:

          • 听起来很熟悉。你能举个例子吗?
          • 如果我想返回相同类型的新实例,这似乎不起作用?
          • 是 - this.type 是路径相关的:只返回当前实例才有效
          猜你喜欢
          • 2016-07-04
          • 2016-09-13
          • 1970-01-01
          • 1970-01-01
          • 2016-11-28
          • 2021-01-10
          • 1970-01-01
          • 2015-06-03
          • 2012-12-19
          相关资源
          最近更新 更多