我想要一个密封的特性,它具有一个返回的声明方法 扩展特征的实际类。我应该使用抽象类型,参数类型或 有没有其他好办法解决这个问题?
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 = ...
}
答案 0 :(得分:4)
它们大多可以互换。根据Odersky的说法,原因主要在于完整性:类似于方法和字段(值)可以是抽象的或作为参数传递的事实,类型也是如此。
当您打算混合使用相同类型名称的多个特征时,最好使用抽象类型。使用类型参数,您需要将类型显式传递给每个
这是一篇解释所有这些内容的文章:http://www.artima.com/weblogs/viewpost.jsp?thread=270195
答案 1 :(得分:2)
你可以写:
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]
)。
答案 2 :(得分: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 :(得分:1)
编辑 - 以下是我的原始答案。您的评论表明您希望返回匹配类型的任意实例,但我并不认为这在任何方面都是明智的。 假设它是通过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
答案 4 :(得分:1)
trait Foo[A <: Foo[A]]
如果A是Foo [A]的子类型,则该特征只能混合在一起,唯一满足该类型的是Foo类被混入的类型。我在Lift中的Mapper特征中看到了这个解决方案。