扩展特征和类型

时间:2010-11-29 11:01:29

标签: scala

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

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 = ...
}

5 个答案:

答案 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特征中看到了这个解决方案。