自键入可以与抽象类型一起使用吗?

Law*_*eld 3 generics scala scala-2.10

我试图在不使用泛型的情况下实现F-有界多态性.我还需要使用自我键入,因为我将引用this并期望将其键入为子类型.

trait MyTrait[T] { self: Self => // Compilation error: cannot reference 'Self'
   type Self <: MyTrait[T]

   def doSomethingWithSubtype() {
      ...
   }
}
Run Code Online (Sandbox Code Playgroud)

我可以很容易地使用类型参数(即泛型)来实现这一点,但是想知道我是否缺少某些内容来进行上述编译.你能用这种方式使用抽象类型吗?

类似的问题:

这些为类似问题提供了解决方法,让我相信以上是不可能的?

具有抽象类型而不是参数类型的F-束缚多态?

通过类型成员而不是类型参数进行F-限制量化?

gou*_*ama 5

您可以自我键入一个抽象类型,但有一个棘手的限制:它必须在您的特征之外定义,但仍然在允许实现以某种类型实现它的范围内.你可以通过将整个事物包装成一个特征来做到这一点:

trait MyTraitSystem {
    type TraitImpl <: MyTrait

    trait MyTrait { self: TraitImpl =>
        def doSomething(t: TraitImpl): String
    }
}

// with an example implementation of the trait:

object MyImpl extends MyTraitSystem {
  case class TraitImpl(data: String) extends MyTrait {
    def doSomething(t: TraitImpl): String = t.data + " " + data
  }
}
Run Code Online (Sandbox Code Playgroud)

这相当于使用类型参数的此版本:

trait MyTrait[T <: MyTrait[_]] { self: T =>
  def doSomething(t: T): String
}

// with an example implementation of the trait:

case class TraitImpl(data: String) extends MyTrait[TraitImpl] {
  def doSomething(t: TraitImpl): String = t.data + " " + data
}
Run Code Online (Sandbox Code Playgroud)

除了import MyImpl._抽象类型版本之外,它们可以以相同的方式使用:

scala> import MyImpl._
    import MyImpl._

scala> val a = TraitImpl("hello")
a: MyImpl.TraitImpl = TraitImpl(hello)

scala> val b = TraitImpl("world")
b: MyImpl.TraitImpl = TraitImpl(world)

scala> b.doSomething(a)
res0: String = hello world
Run Code Online (Sandbox Code Playgroud)

抽象类型版本更详细,但它有效.你还需要随身携带一个MyTraitSystem需要使用的方法/类/ ... TraitImpl以提供类型:

object SomewhereElse {
  def doSomethingElse(s: MyTraitSystem)(t: s.TraitImpl) = 
    ??? // s.TraitImpl is the implementation type
}
Run Code Online (Sandbox Code Playgroud)

与类型参数版本相比:

object SomewhereElse {
  def doSomethingElse[T <: MyTrait[_]](t: MyTrait[T]) = 
    ??? // T is the implementation type
}
Run Code Online (Sandbox Code Playgroud)

这可能只是其中几种方法之一,但我认为没有任何方法可以匹配基于类型参数的版本的简洁性.