Scala之旅-抽象类型

Scala之旅-抽象类型

抽象类型(Abstract Types)

特征和抽象类可以有一个抽象类型成员。这意味着要由具体实现定义真正的类型。下面是一个例子:

trait Buffer {
  type T
  val element: T
}

这里我们定义了一个抽象类型T,用来描述element的类型。我们可以在一个抽象类中扩展这个特征,并且给T增加一个类型上界,使得T更加特定明确。

abstract class SeqBuffer extends Buffer {
  type U
  type T <: Seq[U]
  def length = element.length
}

注意我们是如何用另外一个抽象类型U作为一个类型上界的。通过声明类型T必须是Seq[U]的子类型,类SeqBuffer允许我们只能在buffer中存储sequences。

带有抽象类型成员的特征或者类经常与匿名类实例结合使用。为了阐明该用法,现在我们看一个处理sequence buffer的程序,这个sequence buffer指向的是一个整数列表。

abstract class IntSeqBuffer extends SeqBuffer {
  type U = Int
}

def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
  new IntSeqBuffer {
       type T = List[U]
       val element = List(elem1, elem2)
     }
val buf = newIntSeqBuf(7, 8)
println("length = " + buf.length)
println("content = " + buf.element)

这里newIntSeqBuf使用了IntSeqBuffer的匿名类实现(也就是new IntSeqBuffer),将类型T设置为List[Int]。

我们可以将抽象类型成员转化为类的类型参数,反之亦然。下面是上面代码只用类型参数的版本:

abstract class Buffer[+T] {
  val element: T
}
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
  def length = element.length
}
def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
  new SeqBuffer[Int, List[Int]] {
    val element = List(e1, e2)
  }
val buf = newIntSeqBuf(7, 8)
println("length = " + buf.length)
println("content = " + buf.element)

注意:为了隐藏方法newIntSeqBuf返回的对象的具体sequence实现类型,我们需要使用变性注解(+T <: Seq[U])。此外,还有一些情况是无法用类型参数代替抽象类型的。

参考资料

本文译自Tour Of Scala – Abstract Types

上一篇:Scala之旅-内部类

下一篇:Scala之旅-复合类型

发表评论

电子邮件地址不会被公开。 必填项已用*标注