继承保持类型的特征

时间:2011-12-08 21:20:30

标签: scala

我对Scala很陌生,但仍然对其复杂的类型系统感到困惑。

我尝试解决以下问题。我想设计属于可变双向链表(以及更复杂的数据结构,如堆)的成员的类。当然,我的目标是能够在恒定的时间内从数据结构中删除对象。

我设计了以下特质:

trait DLLMember {
  var next: DLLMember = this
  var prev: DLLMember = this

  ...
}

使用一些其他方法在列表中添加和删除对象。

问题是,当我在实际上课时,请说:

class IntInDL(val v: Int) extends DLLMember

在解析我的列表时,IntInDL.next会返回一个DLLMember类型而不是IntInDL,我必须强制转换它来检索值:这不是很好......

有没有办法利用Scala的类型系统来保持我的工作类型安全?

1 个答案:

答案 0 :(得分:6)

这是一个小迂回,但以下应该有效:

trait DLLMember[T >: Null <: DLLMember[T]] { self : T =>
  var next: T = this
  var prev: T = this
  ...
}

class IntInDL(val v: Int) extends DLLMember[IntInDL]

var i = new IntInDL(3)
println(i.next.v) //prints 3
i.next = null //is valid
i.next = new IntInDL(1) //is valid

基本上,这里发生的是你用self : T =>说明类型参数T必须是应用此特征的类的超类。当您在IntInDL中使用特征时,现在已知nextprev变量必须属于IntInDL的某个子类型,因为您将其作为类型参数提供。因此,您可以直接使用其成员,而无需进行强制转换。

如果您提供了一些不属于层次结构的其他任意类型,例如class IntInDL(val v: Int) extends DLLMember[String],那么它将无法编译。