好程序员大数据

好程序员大数据培训分享Scala系列之泛型

2019-10-10  本文已影响0人  ab6973df9221

  好程序员大数据培训分享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。

valstack = new Stack[Int]stack.push(1)stack.push(2)println(stack.pop)  // prints 2println(stack.pop)  // prints 1

1.协变

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

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

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

objectCovarianceTest 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 Animalcase class Dog(name: String) extends Animal

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

abstract class Printer[-A] {  def print(value: A): Unit}classAnimalPrinter extends Printer[Animal] {  def print(animal: Animal): Unit =    println("The animal's name is: " + animal.name)}classCatPrinter extends Printer[Cat] {  def print(cat: Cat): Unit =    println("The cat's name is: " + cat.name)}

逆变的测试

objectContravarianceTest extends App {  valmyCat: Cat = Cat("Boots")//定义参数类型为Printer[Cat]  def printMyCat(printer: Printer[Cat]): Unit = {    printer.print(myCat)  }  valcatPrinter: Printer[Cat] = new CatPrinter  valanimalPrinter: Printer[Animal] = new AnimalPrinter  printMyCat(catPrinter)    //可以传入参数类型为Printer[Animal]   printMyCat(animalPrinter)}

3.上界

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

abstract class Animal { def name: String}abstract classPet extends Animal {}classCat extends Pet {  override defname: String = "Cat"}classDog extends Pet {  override defname: String = "Dog"}classLion extends Animal {  override defname: String = "Lion"}//参数类型须是Pet类型的子类class PetContainer[P <: Pet](p: P) {  def pet: P = p}//Dog是Pet类型的子类valdogContainer = new PetContainer[Dog](new Dog)//Cat是Pet类型的子类valcatContainer = new PetContainer[Cat](new Cat)//Lion不是Pet类型的子类,编译通不过//  val lionContainer = new PetContainer[Lion](new Lion)

4.下界

语法 B >: A表示参数类型或抽象类型 B须是类型A的父类。通常,A是类的类型参数,B是方法的类型参数。

好程序员大数据学习路线

上面这段代码,因为作为协变类型的B,出现在需要逆变类型的函数参数中,导致编译不通过。解决这个问题,就需要用到下界的概念。

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 head: B = h  def tail: Node[B] = t}case class Nil[+B]() extends Node[B] {  def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)}

测试

trait Birdcase class AfricanSwallow() extends Birdcase class EuropeanSwallow() extends Birdval africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())val birdList: Node[Bird] = africanSwallowListbirdList.prepend(new EuropeanSwallow)

5 视界(view bounds)

注意:已过时,了解即可

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

class Pair_Int[T <% Comparable[T]] (valfirst: T, val second: T){  defbigger = if(first.compareTo(second) > 0) first else second}class Pair_Better[T <% Ordered[T]](valfirst: T, val second: T){  defsmaller = if(first < second) first else second}object View_Bound {  def main(args: Array[String]) {  // 因为Pair[String] 是Comparable[T]的子类型, 所以String有compareTo方法    valpair = 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_Context[T : Ordering](valfirst: T, val second: T){  def smaller(implicit ord: Ordering[T]) =    if(ord.compare(first, second) < 0) first else second}object Context_Bound {  def main(args: Array[String]) {    valpair = new Pair_Context("Spark", "Hadoop")    println(pair.smaller)    val int= new Pair_Context(3, 5)    println(int.smaller)  }}

好程序员大数据培训官网:http://www.goodprogrammer.org/bigdata.shtml

上一篇下一篇

猜你喜欢

热点阅读