4. Scala的静态类型
Scala是静态类型的,它拥有一个强大的类型系统,静态地强制以安全、一致的方式使用抽象,我们通过下面几个特征来一一说明:
- 泛类型
- 型变
- 类型上界
- 类型下界
- 内部类
- 抽象类型
- 复合类型
- 自类型
- 隐式参数
- 隐式转换
- 多态方法
- 类型推断
通过这些特性,为安全可重用的编程抽象以及类型安全的扩展提供了强大的基础。
泛类型
和java一样,Scala也有泛型的概念,在scala里面泛型是使用方括号 [] 来接受类型参数的。通常使用字母A来作为参数标志符,当然你也可以使用其他任意的参数名称。
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
}
}
要使用一个泛类型,将一个具体的类型替换掉A即可。
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop) // prints 2
println(stack.pop) // prints 1
上面的例子中,实例对象接收整型值,如果该类型有子类型,子类型也是可以传入的。
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)
型变
型变主要是针对泛类型来说的,用来表示这种复杂类型的相关性。型变主要有协变,逆变和不变三种情况。在类型系统中使用型变允许我们在复杂类型之间建立直观的连接,而缺乏型变则会限制类抽象的重用性。
class Foo[+A] // A covariant class
class Bar[-A] // A contravariant class
class Baz[A] // An invariant class
协变
协变使用+A来表示。对于某些类 class List[+A],使 A 成为协变意味着对于两种类型 C 和 D,如果 C 是 D 的子类型,那么 List[C] 就是 List[D] 的子类型。 这允许我们使用泛型来创建非常有用和直观的子类型关系。
abstract class Animal {
def name: String
}
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal