Scala 游览

抽象类型成员

语言

抽象类型(例如特质和抽象类)反过来可以具有抽象类型成员。这意味着具体实现定义实际类型。这是一个示例

trait Buffer {
  type T
  val element: T
}
trait Buffer:
  type T
  val element: T

此处我们定义了一个抽象 type T。它用于描述 element 的类型。我们可以在抽象类中扩展此特质,向 T 添加上型界,使其更具体。

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

请注意,我们如何在 T 的上型界的规范中使用另一个抽象类型 U。此 class SeqBuffer 允许我们仅将序列存储在缓冲区中,方法是声明类型 T 必须是新抽象类型 USeq[U] 的子类型。

具有抽象类型成员的特质或 通常与匿名类实例化结合使用。为了说明这一点,我们现在来看一个处理引用整数列表的序列缓冲区的程序

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)
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)
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)

请注意,我们必须使用方差注解+T <: Seq[U]),以便隐藏从方法 newIntSeqBuf 返回的对象的具体序列实现类型。此外,在某些情况下,无法用类型参数替换抽象类型成员。

本页面的贡献者