您可以将自己类型化为抽象类型,但有一个棘手的限制:它必须在您的 trait 之外定义,但仍以允许实现使用某种类型实现它的方式在范围内。您可以通过将整个事物包装成一个特征来做到这一点:
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
}
}
这等效于使用类型参数的此版本:
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
}
除了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
抽象类型的版本更冗长,但它有效。MyTraitSystem
您还需要在需要使用的任何方法/类/...中携带 aTraitImpl
以提供类型:
object SomewhereElse {
def doSomethingElse(s: MyTraitSystem)(t: s.TraitImpl) =
??? // s.TraitImpl is the implementation type
}
与类型参数版本相比:
object SomewhereElse {
def doSomethingElse[T <: MyTrait[_]](t: MyTrait[T]) =
??? // T is the implementation type
}
这可能只是执行此操作的几种方法之一,但我认为没有任何方法可以与基于类型参数的版本的简洁性相匹配。