特质和抽象类可以拥有抽象类型的成员。这意味着具体的实现可以定义实际的类型,下面是示例:
1 | trait Buffer { |
这里我们定义了一个抽象的type T
,用来描述element
的类型。我们可以在抽象类中继承该特质,并为T
增加了一个类型上界使之更为具体。
1 | abstract class SeqBuffer extends Buffer { |
注意我们将如何使用作为类型上界的另一个抽象的type U
。class SeqBuffer
通过声明一个Seq[U]
(这里U
是一个新的抽象类型)的子类型T
,使得我们在一个Buffer
中只能存储序列。
拥有抽象成员的特质和类经常与匿名类的实例化结合使用。为了说明这点,我们来看一段程序,其中涉及到一个指向整数列表的序列缓冲:
1 | abstract class IntSeqBuffer extends SeqBuffer { |
这里的工厂方法newIntSeqBuf
用到了IntSeqBuf
的一个匿名实现类(即new IntSeqBuffer
),并将type T
设置为一个List[Int]
。
也可以将抽象类型成员转换为类的类型参数,反之亦然。下面是上述代码的另外一个版本,但仅仅使用了类型参数:
1 | abstract class Buffer[+T] { |
为了隐藏方法new IntSeqBuf
返回的对象的具体序列实现类型,我们需要用到型变注解(即+T <: Seq[U]
)。此外,有些场景下是不能用类型参数来替换抽象类型的。