好程序员大数据学习路线分享Scala系列之泛型

  好程序员大数据学习路线分享Scala系列之泛型,带有一个或多个类型参数的类是泛型的。程序员

泛型类的定义:ide

//带有类型参数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 = {oop

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大数据

1.协变
定义一个类型List[+A],若是A是协变的,意思是:对类型A和B,A是B的子类型,那么List[A]是List[B]的子类型。this

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

Scala标准库有一个泛型类sealed abstract class List[+A],由于其中的类型参数是协变的,那么下面的程序调用时成功的。scala

object CovarianceTest extends App {

//定义参数类型List[Animal]

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"))
//传入参数类型为List[Cat]
printAnimalNames(cats)
// Whiskers
// Tom
//传入参数类型为List[Dog]
printAnimalNames(dogs)
// Fido
// Rex
}

2.逆变
定义一个类型Writer[-A],若是A是逆变的,意思是:对类型A和B,A是B的子类型,那么Writer[B]是Writer[A]的子类型。

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

定义对应上述类进行操做的打印信息类

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")

//定义参数类型为Printer[Cat]
def printMyCat(printer: Printer[Cat]): Unit = {

printer.print(myCat)

}

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

printMyCat(catPrinter)

//能够传入参数类型为Printer[Animal]

printMyCat(animalPrinter)
}

3.上界
上界定义: T <: A ,表示类型变量T 必须是 类型A 子类

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"
}
//参数类型须是Pet类型的子类
class PetContainerP <: Pet {
def pet: P = p
}
//Dog是Pet类型的子类
val dogContainer = new PetContainerDog
//Cat是Pet类型的子类
val catContainer = new PetContainerCat
//Lion不是Pet类型的子类,编译通不过
// val lionContainer = new PetContainerLion

4.下界
语法 B >: A 表示参数类型或抽象类型 B 须是类型A的父类。一般,A是类的类型参数,B是方法的类型参数。

图片1.png

上面这段代码,由于做为协变类型的B,出如今须要逆变类型的函数参数中,致使编译不经过。解决这个问题,就须要用到下界的概念。

trait Node[+B] {
def prependU >: B: Node[U]
}

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

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

测试

trait Bird
case class AfricanSwallow() extends Bird
case class EuropeanSwallow() extends Bird

val africanSwallowList= ListNodeAfricanSwallow, Nil())
val birdList: Node[Bird] = africanSwallowList
birdList.prepend(new EuropeanSwallow)

5 视界(view bounds)
注意:已过期,了解便可

视界定义: A <% B ,表示类型变量A 必须是 类型B`的子类,或者A可以隐式转换到B

class Pair_Int[T <% Comparable[T]] (val first: T, val second: T){
def bigger = if(first.compareTo(second) > 0) first else second
}

class Pair_Better[T <% Ordered[T]](val first: T, val second: T){
def smaller = if(first < second) first else second
}
object View_Bound {

def main(args: Array[String]) {
// 由于Pair[String] 是Comparable[T]的子类型, 因此String有compareTo方法

val pair = new Pair_Int("Spark", "Hadoop");
println(pair.bigger)

/**
  * Scala语言里 Int类型没有实现Comparable;
  * 那么该如何解决这个问题那;
  * 在scala里 RichInt实现了Comparable, 若是咱们把int转换为RichInt类型就能够这样实例化了.
  * 在scala里 <% 就起这个做用, 须要修改Pair里的 <: 为<% 把T类型隐身转换为Comparable[Int]
  * String能够被转换为RichString. 而RichString是Ordered[String] 的子类.
  */
val pair_int = new Pair_Int(3 ,45)
println(pair_int.bigger)

val pair_better = new Pair_Better(39 ,5)
println(pair_better.smaller)

}

}

6 上下文界定(context bounds)
上下文界定的形式为 T : M, 其中M 必须为泛型类, 必须存在一个M[T]的隐式值.

class Pair_ContextT : Ordering{
def smaller(implicit ord: Ordering[T]) =

if(ord.compare(first, second) < 0) first else second

}

object Context_Bound {

def main(args: Array[String]) {

val pair = new Pair_Context("Spark", "Hadoop")
println(pair.smaller)

val int = new Pair_Context(3, 5)
println(int.smaller)

}

}

相关文章
相关标签/搜索