1
1
---
2
2
layout : tour
3
- title : Abstract Types
3
+ title : 抽象类型
4
4
5
5
discourse : false
6
6
@@ -13,3 +13,63 @@ language: zh-cn
13
13
next-page : compound-types
14
14
previous-page : inner-classes
15
15
---
16
+
17
+ 特质和抽象类可以包含一个抽象类型成员,意味着实际类型可由具体实现来确定。例如:
18
+
19
+ ``` tut
20
+ trait Buffer {
21
+ type T
22
+ val element: T
23
+ }
24
+ ```
25
+ 这里定义的抽象类型` T ` 是用来描述成员` element ` 的类型的。通过抽象类来扩展这个特质后,就可以添加一个类型上边界来让抽象类型` T ` 变得更加具体。
26
+
27
+ ``` tut
28
+ abstract class SeqBuffer extends Buffer {
29
+ type U
30
+ type T <: Seq[U]
31
+ def length = element.length
32
+ }
33
+ ```
34
+ 注意这里是如何借助另外一个抽象类型` U ` 来限定类型上边界的。通过声明类型` T ` 只可以是` Seq[U] ` 的子类(其中U是一个新的抽象类型),这个` SeqBuffer ` 类就限定了缓冲区中存储的元素类型只能是序列。
35
+
36
+ 含有抽象类型成员的特质或类([ classes] ( classes.html ) )经常和匿名类的初始化一起使用。为了能够阐明问题,下面看一段程序,它处理一个涉及整型列表的序列缓冲区。
37
+
38
+ ``` tut
39
+ abstract class IntSeqBuffer extends SeqBuffer {
40
+ type U = Int
41
+ }
42
+
43
+
44
+ def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
45
+ new IntSeqBuffer {
46
+ type T = List[U]
47
+ val element = List(elem1, elem2)
48
+ }
49
+ val buf = newIntSeqBuf(7, 8)
50
+ println("length = " + buf.length)
51
+ println("content = " + buf.element)
52
+ ```
53
+ 这里的工厂方法` newIntSeqBuf ` 使用了` IntSeqBuf ` 的匿名类实现方式,其类型` T ` 被设置成了` List[Int] ` 。
54
+
55
+ 把抽象类型成员转成类的类型参数或者反过来,也是可行的。如下面这个版本只用了类的类型参数来转换上面的代码:
56
+
57
+ ``` tut
58
+ abstract class Buffer[+T] {
59
+ val element: T
60
+ }
61
+ abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
62
+ def length = element.length
63
+ }
64
+
65
+ def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
66
+ new SeqBuffer[Int, List[Int]] {
67
+ val element = List(e1, e2)
68
+ }
69
+
70
+ val buf = newIntSeqBuf(7, 8)
71
+ println("length = " + buf.length)
72
+ println("content = " + buf.element)
73
+ ```
74
+
75
+ 需要注意的是为了隐藏从方法` newIntSeqBuf ` 返回的对象的具体序列实现的类型,这里的[ 型变标号] ( variances.html ) (` +T <: Seq[U] ` )是必不可少的。此外要说明的是,有些情况下用类型参数替换抽象类型是行不通的。
0 commit comments