小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

大數(shù)據(jù)學習路線分享Scala系列之泛型

 好程序員IT 2019-10-10

  大數(shù)據(jù)學習路線分享Scala系列之泛型,帶有一個或多個類型參數(shù)的類是泛型的。

泛型類的定義:

 //帶有類型參數(shù)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
  }
}

泛型類的使用,用具體的類型代替類型參數(shù)A。

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

1.協(xié)變

定義一個類型List[+A],如果A是協(xié)變的,意思是:對類型A和B,A是B的子類型,那么List[A]是List[B]的子類型。

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

Scala標準庫有一個泛型類sealed abstract class List[+A],因為其中的類型參數(shù)是協(xié)變的,那么下面的程序調用時成功的。

object CovarianceTest extends App {
    //定義參數(shù)類型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"))
  //傳入?yún)?shù)類型為List[Cat]
  printAnimalNames(cats)
  // Whiskers
  // Tom
  //傳入?yún)?shù)類型為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")

//定義參數(shù)類型為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)
    //可以傳入?yún)?shù)類型為Printer[Animal]
  printMyCat(animalPrinter)
}

3.上界

上界定義: 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"
}
//參數(shù)類型須是Pet類型的子類
class PetContainer[P <: Pet](p: P) {
  def pet: P = p
}
//DogPet類型的子類
val dogContainer = new PetContainer[Dog](new Dog)
//CatPet類型的子類
val catContainer = new PetContainer[Cat](new Cat)
//Lion不是Pet類型的子類,編譯通不過
//  val lionContainer = new PetContainer[Lion](new Lion)

4.下界

語法 B >: A 表示參數(shù)類型或抽象類型須是類型A的父類。通常,A是類的類型參數(shù),B是方法的類型參數(shù)。


上面這段代碼,因為作為協(xié)變類型的B,出現(xiàn)在需要逆變類型的函數(shù)參數(shù)中,導致編譯不通過。解決這個問題,就需要用到下界的概念。

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 Bird
case class AfricanSwallow() extends Bird
case class EuropeanSwallow() extends Bird


val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), 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]的子類型, 所以StringcompareTo方法
    val pair = new Pair_Int("Spark", "Hadoop");
    println(pair.bigger)

    /**
      * Scala語言里 Int類型沒有實現(xiàn)Comparable;
      * 那么該如何解決這個問題那;
      * scalaRichInt實現(xiàn)了Comparable, 如果我們把int轉換為RichInt類型就可以這樣實例化了.
      * scala<% 就起這個作用, 需要修改Pair里的 <: <% T類型隱身轉換為Comparable[Int]
      * String可以被轉換為RichString. RichStringOrdered[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](val first: 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]) {

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

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

  }

}

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多