Scala之旅——泛型类

泛型类是接受类型作为参数的类。这对于集合类特别有用。

定义一个泛型类

泛型类使用方括号[]接受类型作为参数。尽管可以使用任何参数名,但是一般约定使用字母A来作为类型参数标识符。

1
2
3
4
5
6
7
8
9
10
class Stack[A] {
private var elements: List[A] = Nil
def push(x: A) { elements = x :: elements }
def peek: A = elements.head
def pop(): A = {
val currentTop = peek
elements = elements.tail
currentTop
}
}

这里Stack类的实现接受任意类型A作为参数。这意味着下面的列表var elements: List[A] = Nil,只能存储A类型的元素。方法def push仅仅接受类型A的参数(注意: elements = x :: elements 通过将x加到当前这个elements的头部,来将elements重新分配到一个新的列表)。

用法

要使用一个泛型类,就将类型替换A放在方括号中。

1
2
3
4
5
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop) // prints 2
println(stack.pop) // prints 1

上述的stack实例仅接受Int类型。然而,如果类型参数有子类型,下面的做法也能通过:

1
2
3
4
5
6
7
8
9
10
class Fruit
class Apple extends Fruit
class Banana extends Fruit

val stack = new Stack[Fruit]
val apple = new Apple
val banana = new Banana

stack.push(apple)
stack.push(banana)

AppleBanana都继承自Fruit,因此我们可以把applebanana加入到栈Fruit中。

注意:泛型的子类型是不可变的。这意味着如果有个字符类型的栈Stack[Char],那么它是不能作为一个整数类型的栈Stack[Int]来使用的。这听起来有点不对劲,事实上我们应该能够把纯整数放进一个字符栈中的。总之,只有在B=A的时候,Stack[A]才是Stack[B]的子类型。这个其实是有局限性的,于是Scala提供了一种类型参数的注解机制来控制泛型类型的子类型的行为。

小鹏 wechat
公众号:数据Man
0%