# Scala教程之:静态类型

04/11 20:53

### 文章目录

Scala是静态类型的，它拥有一个强大的类型系统，静态地强制以安全、一致的方式使用抽象，我们通过下面几个特征来一一说明：

• 泛类型
• 型变
• 类型上界
• 类型下界
• 内部类
• 抽象类型
• 复合类型
• 自类型
• 隐式参数
• 隐式转换
• 多态方法
• 类型推断

## 泛类型

``````class Stack[A] {
private var elements: List[A] = Nil
def push(x: A) { elements = x :: elements }
def pop(): A = {
val currentTop = peek
elements = elements.tail
currentTop
}
}``````

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

### 协变

``````abstract class Animal {
def name: String
}
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal``````

List[Cat]和List[Dog]都是List[Animal]的子类。

``````object CovarianceTest extends App {
def printAnimalNames(animals: List[Animal]): Unit = {
animals.foreach { animal =>
println(animal.name)
}
}

val cats: List[Cat] = List(Cat("Whiskers"), Cat("Tom"))
val dogs: List[Dog] = List(Dog("Fido"), Dog("Rex"))

printAnimalNames(cats)
// Whiskers
// Tom

printAnimalNames(dogs)
// Fido
// Rex
}``````

### 逆变

``````abstract class Printer[-A] {
def print(value: A): Unit
}``````

``````class AnimalPrinter extends Printer[Animal] {
def print(animal: Animal): Unit =
println("The animal's name is: " + animal.name)
}

class CatPrinter extends Printer[Cat] {
def print(cat: Cat): Unit =
println("The cat's name is: " + cat.name)
}``````

``````object ContravarianceTest extends App {
val myCat: Cat = Cat("Boots")

def printMyCat(printer: Printer[Cat]): Unit = {
printer.print(myCat)
}

val catPrinter: Printer[Cat] = new CatPrinter
val animalPrinter: Printer[Animal] = new AnimalPrinter

printMyCat(catPrinter)
printMyCat(animalPrinter)
}``````

## 类型上界

``````abstract class Animal {
def name: String
}

abstract class Pet extends Animal {}

class Cat extends Pet {
override def name: String = "Cat"
}

class Dog extends Pet {
override def name: String = "Dog"
}

class Lion extends Animal {
override def name: String = "Lion"
}

class PetContainer[P <: Pet](p: P) {
def pet: P = p
}

val dogContainer = new PetContainer[Dog](new Dog)
val catContainer = new PetContainer[Cat](new Cat)

// this would not compile
val lionContainer = new PetContainer[Lion](new Lion)``````

``type arguments [Lion] do not conform to class PetContainer's type parameter bounds [P <: Pet]``

## 类型下界

``````trait Node[+B] {
def prepend(elem: B): Node[B]
}

case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend(elem: B): ListNode[B] = ListNode(elem, this)
def tail: Node[B] = t
}

case class Nil[+B]() extends Node[B] {
def prepend(elem: B): ListNode[B] = ListNode(elem, this)
}``````

``````trait Node[+B] {
def prepend[U >: B](elem: U): Node[U]
}

case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
def tail: Node[B] = t
}

case class Nil[+B]() extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
}``````

## 内部类

``````class Graph {
class Node {
var connectedNodes: List[Node] = Nil
def connectTo(node: Node) {
if (!connectedNodes.exists(node.equals)) {
connectedNodes = node :: connectedNodes
}
}
}
var nodes: List[Node] = Nil
def newNode: Node = {
val res = new Node
nodes = res :: nodes
res
}
}``````

``````val graph1: Graph = new Graph
val node1: graph1.Node = graph1.newNode
val node2: graph1.Node = graph1.newNode
val node3: graph1.Node = graph1.newNode
node1.connectTo(node2)
node3.connectTo(node1)``````

``````val graph1: Graph = new Graph
val node1: graph1.Node = graph1.newNode
val node2: graph1.Node = graph1.newNode
node1.connectTo(node2)      // legal
val graph2: Graph = new Graph
val node3: graph2.Node = graph2.newNode
node1.connectTo(node3)      // illegal!``````

``````class Graph {
class Node {
var connectedNodes: List[Graph#Node] = Nil
def connectTo(node: Graph#Node) {
if (!connectedNodes.exists(node.equals)) {
connectedNodes = node :: connectedNodes
}
}
}
var nodes: List[Node] = Nil
def newNode: Node = {
val res = new Node
nodes = res :: nodes
res
}
}``````

## 抽象类型

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

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

## 复合类型

``````trait Cloneable extends java.lang.Cloneable {
override def clone(): Cloneable = {
super.clone().asInstanceOf[Cloneable]
}
}
trait Resetable {
def reset: Unit
}``````

``````def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {
//...
}``````

## 自类型

``````trait User {
}

trait Tweeter {
this: User =>  // 重新赋予 this 的类型
def tweet(tweetText: String) = println(s"\$username: \$tweetText")
}

class VerifiedTweeter(val username_ : String) extends Tweeter with User {  // 我们混入特质 User 因为 Tweeter 需要
}

val realBeyoncé = new VerifiedTweeter("Beyoncé")
realBeyoncé.tweet("Just spilled my glass of lemonade")  // 打印出 "real Beyoncé: Just spilled my glass of lemonade"``````

## 隐式参数

Scala查找参数的位置有两个地方：

• 首先查找可以直接访问的隐式定义和隐式参数。
• 然后，它在所有伴生对象中查找与隐式候选类型相关的有隐式标记的成员。

``````abstract class Monoid[A] {
def add(x: A, y: A): A
def unit: A
}

object ImplicitTest {
implicit val stringMonoid: Monoid[String] = new Monoid[String] {
def add(x: String, y: String): String = x concat y
def unit: String = ""
}

implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
def add(x: Int, y: Int): Int = x + y
def unit: Int = 0
}

def sum[A](xs: List[A])(implicit m: Monoid[A]): A =
if (xs.isEmpty) m.unit

def main(args: Array[String]): Unit = {
println(sum(List(1, 2, 3)))       // uses IntMonoid implicitly
println(sum(List("a", "b", "c"))) // uses StringMonoid implicitly
}
}``````

intMonoid 是一个隐式定义，可以在main中直接访问。 并且它的类型也正确，因此它会被自动传递给 sum 方法。

## 隐式转换

``````import scala.language.implicitConversions

implicit def list2ordered[A](x: List[A])
(implicit elem2ordered: A => Ordered[A]): Ordered[List[A]] =
new Ordered[List[A]] {
//replace with a more useful implementation
def compare(that: List[A]): Int = 1
}``````

``````import scala.language.implicitConversions

implicit def int2Integer(x: Int) =
java.lang.Integer.valueOf(x)``````

## 多态方法

Scala中多态是通过类型和值的参数化来实现的。 如下所示：

``````def listOfDuplicates[A](x: A, length: Int): List[A] = {
if (length < 1)
Nil
else
x :: listOfDuplicates(x, length - 1)
}
println(listOfDuplicates[Int](3, 4))  // List(3, 3, 3, 3)
println(listOfDuplicates("La", 8))  // List(La, La, La, La, La, La, La, La)``````

## 类型推断

Scala 编译器通常可以推断出表达式的类型，因此你不必显式地声明它。

``val businessName = "Montreux Jazz Café"``

``def squareOf(x: Int) = x * x``

``````case class MyPair[A, B](x: A, y: B)
val p = MyPair(1, "scala") // type: MyPair[Int, String]

def id[T](x: T) = x
val q = id(1)              // type: Int``````

0
0 收藏

0 评论
0 收藏
0