Scala之旅:抽象类型

Scala之旅:抽象类型
A Tour of Scala: Abstract Types
 
在Scala中,类通过值(构造函数参数)与类型(如果类是泛型)被参数化(parameterized)。为了保持一致性,值无法成为对象成员,只有拥有值的类型才能成为对象成员。成员的两种形态可以是具体的或抽象的。
 
以下范例展示了如何将一个延迟值以及一个抽象类型都定义为Buffer类的成员。
abstract class Buffer {
  type T
  val element: T
}
 
抽象类型是一种没有精确地定义细节特性(identity)的类型。在以上范例中,我们仅仅知道每一个Buffer类的对象都有一个类型成员T,不过这个Buffer类的定义并没有告诉我们这个类型成员T明确对应了哪一种类型。与值定义相同,我们可以在子类中重写(override)类型定义。于是我们便可以通过收紧类型的界限(该界限描述了这个抽象类型实例化后可能会变成什么样子)来展示更多有关一个抽象类型的信息。
 
在下面这段程序中我们得到一个SeqBuffer类,这个类通过声明T类型必须为一个新的抽象类型U的子类型来实现仅仅储存缓冲区(buffer)中的序列(sequence)这一功能:
 
abstract class SeqBuffer extends Buffer {
  type U
  type T <: Seq[U]
  def length = element.length
}
 
有抽象类型成员的特征或类经常与匿名类实例化被一同使用。以下这个示例将展示这一点――我们用这个程序来处理引自整数list(列表)的序列缓冲:
 
abstract class IntSeqBuffer extends SeqBuffer {
  type U = Int
}
object AbstractTypeTest1 extends Application {
  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方法的返回类型引自Buffer特征的一个特例化,其中的U类型已经等同于Int。在newIntSeqBuf方法内部的匿名类实例化当中,我们还有一个相似的类型别名(type alias)。这里我们创建了IntSeqBuffer的一个新实例,其中T类型引自List[Int]。
 
请注意,我们经常可以将抽象类型成员转变为类的类型参数(type parameter),反之亦然。以下是上述程序的类型参数版代码:
 
abstract class Buffer[+T] {
  val element: T
}
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
  def length = element.length
}
object AbstractTypeTest2 extends Application {
  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返回对象的那个序列实现类型隐藏起来。另外,也有类型参数无法取代抽象类型的情况。

你可能感兴趣的:(休闲,Scala之旅,抽象类型,型变注释)