使用type member作为自我类型

时间:2015-02-19 16:30:50

标签: scala self-type type-projection

我遇到了一个与一个类型成员对应的递归自我类型的问题:

trait Elem { me =>
  type Peer

  import me.{Peer => Peer0}

  type This <: Elem { type Peer = Peer0 }

  def mkCopy(): This
}

现在我想定义一个方便的特性:

trait ImmutableImpl extends Elem {
  _ : This =>

  def mkCopy(): This = this
}

这不起作用,因为“错误:找不到:输入此内容” :(

下一次尝试:

trait ImmutableImpl[Repr] extends Elem {
  _ : Repr =>

  type This = Repr

  def mkCopy(): This = this
}

此操作失败并显示“错误:覆盖类型此...此类型不兼容”

我只能做这种可憎的事:

trait ImmutableImpl[Peer0, Repr <: Elem { type Peer = Peer0 }] extends Elem {
  _ : Repr =>

  type Peer = Peer0
  type This = Repr

  override def mkCopy(): This = this
}

class IntElem extends ImmutableImpl[Int, IntElem]

在实际情况中,我有更多的类型成员,因此这使得最后一种方法毫无用处,因为每次手动实现mkCopy都需要更多的锅炉板。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

似乎类型参数更适合这种情况。

trait Elem[A] { me: A =>
    def mkCopy(): A = this
}

scala> class Z extends Elem[Z]

scala> (new Z).mkCopy()
res0: Z = Z@3003a3a3

我认为问题是类型成员不在自我类型声明的范围内,而你解决这个问题的方法是使用与另一个特征绑定的结构类型。但是为什么不切断中间人,只使用Elem上的类型参数和自我类型,要求它与参数的类型相同。

答案 1 :(得分:1)

我的解决方法是放宽This上的细化,因为我的API最终似乎不需要这样做:

trait Elem { me =>
  type Peer

  // import me.{Peer => Peer0}

  type This <: Elem // { type Peer = Peer0 }

  def mkCopy(): This
}

trait ImmutableImpl[Repr <: Elem] extends Elem {
  _ : Repr =>

  override type This = Repr

  def mkCopy(): This = this
}

class IntElem extends ImmutableImpl[IntElem] {
  type Peer = Int
}