日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

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

 好程序員IT 2019-10-10

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

泛型類(lèi)的定義:

 //帶有類(lèi)型參數(shù)A的類(lèi)定義
 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
  }
}

泛型類(lèi)的使用,用具體的類(lèi)型代替類(lèi)型參數(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é)變

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

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

Scala標(biāo)準(zhǔn)庫(kù)有一個(gè)泛型類(lèi)sealed abstract class List[+A],因?yàn)槠渲械念?lèi)型參數(shù)是協(xié)變的,那么下面的程序調(diào)用時(shí)成功的。

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

2.逆變

定義一個(gè)類(lèi)型Writer[-A],如果A是逆變的,意思是:對(duì)類(lèi)型A和B,A是B的子類(lèi)型,那么Writer[B]是Writer[A]的子類(lèi)型。

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

定義對(duì)應(yīng)上述類(lèi)進(jìn)行操作的打印信息類(lèi)

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

逆變的測(cè)試

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

//定義參數(shù)類(lèi)型為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ù)類(lèi)型為Printer[Animal]
  printMyCat(animalPrinter)
}

3.上界

上界定義: T <: A ,表示類(lèi)型變量必須是 類(lèi)型子類(lèi)

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ù)類(lèi)型須是Pet類(lèi)型的子類(lèi)
class PetContainer[P <: Pet](p: P) {
  def pet: P = p
}
//DogPet類(lèi)型的子類(lèi)
val dogContainer = new PetContainer[Dog](new Dog)
//CatPet類(lèi)型的子類(lèi)
val catContainer = new PetContainer[Cat](new Cat)
//Lion不是Pet類(lèi)型的子類(lèi),編譯通不過(guò)
//  val lionContainer = new PetContainer[Lion](new Lion)

4.下界

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


上面這段代碼,因?yàn)樽鳛閰f(xié)變類(lèi)型的B,出現(xiàn)在需要逆變類(lèi)型的函數(shù)參數(shù)中,導(dǎo)致編譯不通過(guò)。解決這個(gè)問(wèn)題,就需要用到下界的概念。

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

測(cè)試

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)

注意:已過(guò)時(shí),了解即可

視界定義: A <% B ,表示類(lèi)型變量A 必須是 類(lèi)型B`的子類(lèi),或者A能夠隱式轉(zhuǎn)換到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]) {
  // 因?yàn)?/span>Pair[String] Comparable[T]的子類(lèi)型, 所以StringcompareTo方法
    val pair = new Pair_Int("Spark", "Hadoop");
    println(pair.bigger)

    /**
      * Scala語(yǔ)言里 Int類(lèi)型沒(méi)有實(shí)現(xiàn)Comparable;
      * 那么該如何解決這個(gè)問(wèn)題那;
      * scalaRichInt實(shí)現(xiàn)了Comparable, 如果我們把int轉(zhuǎn)換為RichInt類(lèi)型就可以這樣實(shí)例化了.
      * scala<% 就起這個(gè)作用, 需要修改Pair里的 <: <% T類(lèi)型隱身轉(zhuǎn)換為Comparable[Int]
      * String可以被轉(zhuǎn)換為RichString. RichStringOrdered[String] 的子類(lèi).
      */
    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 必須為泛型類(lèi), 必須存在一個(gè)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)

  }

}

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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多