Scala入門到放棄——泛型(十)

十四、泛型

泛型類

類似於Java,類和特質可以攜帶類型參數

class Student[T, S](var name: T, var age: S) {   // T S K 
												 // <> ---> [T,S,K]
}

object Student {
  def main(args: Array[String]): Unit = {
    // 創建類時,手動指定泛型類型
    val stu = new Student[String, Int]("zs", 18)
    println(stu.name + "\t" + stu.age)

    // 採用自動推斷
    val stu2= new Student("zs", 18)
    println(stu2.name + "\t" + stu2.age)
  }
}

泛型方法和函數

函數和方法也可以帶類型參數

def format[T](x: Array[T]) = {  //類型參數放在方法名之後
  println(x.mkString(","))
}

def format2[T](x: Array[T]): Array[String] = {
  x.map(_ + "")
}

// 調用時,手動指定泛型類型
format[Int](Array(1, 2, 3, 4))
// 或
format(Array(1, 2, 3, 4))

println(format2(Array[Int](1,2,3,4)).mkString("|"))
返回值泛型需要根據傳入參數動態改變

上邊界

語法:[T <: S], 限定T類型必須是S的子類型 ,包含S類型本身

trait Animals

class Dog extends Animals

class Keeper[U <: Animals] {  // 表示Keeper的實現類只能飼養Animal以及Animal的子類
  def keep(a: U): Unit = {
    println("飼養動物:"+a.getClass)
  }
}
object Keeper {
  def main(args: Array[String]): Unit = {
    val dog = new Dog
    new Keeper[Dog]().keep(dog)
  }
}

下邊界

語法:[T >: s] ,限定T類型必須S的父類型

class Animals

class Dog extends Animals

class Car

class Keeper2[T >: Dog] {   // 表示Keeper的實現類只能飼養Dog或者Dog的父類
  def keeper(d: T) {
    println("飼養狗的同類..." + d.getClass)
  }
}

object Keeper2 {
  def main(args: Array[String]): Unit = {
    new Keeper2[Dog].keeper(new Dog)
    new Keeper2[Animals].keeper(new Animals)
    new Keeper2[Car]  //error
  }
}

下邊界範圍:包含父類 間接父類和本身

視圖限定

語法:[T <% S], 運行時嘗試將T類型隱式轉換爲S類型

package generic.viewlimit

import java.text.SimpleDateFormat
import java.util.Date

/**
  * 視圖限定  嘗試通過隱式轉換將T 類型轉換Date類型
  *
  * @param  first 傳進來的是字符串
  *
  */
class Convert[T <% Date](val first: T) {
  def print() = {
    println(first.toLocaleString)
  }
}

object Convert {
  // 定義隱式轉換函數
  implicit def str2Date(str:String):Date = {
    new SimpleDateFormat("yyyy-MM-dd").parse(str)
  }

  def main(args: Array[String]): Unit = {
    val c1 = new Convert[String]("2018-10-10")
    c1.print()
  }
}

上下文限定

上下文界定的形式爲T:M,其中M是另一個泛型類,它要求必須存在一個類型爲M[T]的隱式值。

package generic

/**
  * 1) 要求:使用上下文界定+隱式值的方式,比較兩個Person對象的年齡大小
  * 2) 要求:使用Ordering實現比較
  */
class Person(var name: String, var age: Int)

object Person {
  //1. 聲明一個隱式值
  implicit val ordering: Ordering[Person] = new Ordering[Person]() {
    /**
      * 比較大小的方法
      *
      * @param x
      * @param y
      * @return 1  大於  -1 小於
      */
    override def compare(x: Person, y: Person): Int = {
      if (x.age > y.age) 1
      else -1
    }
  }

  def main(args: Array[String]): Unit = {
    val p1 = new Person("zs", 10)
    val p2 = new Person("ls", 100)

    val tools = new CompareUtils[Person](p1, p2)

    if (tools.comparable() == 1) {
      println("大於")
    } else {
      println("小於")
    }
  }
}

// 上下文限定 T:M  M必須是一個泛型類  M[S]泛型類必須得有個隱式值
class CompareUtils[T: Ordering](p1: T, p2: T) {

  def comparable() = {
    // 獲取隱式值
    val tools = implicitly[Ordering[T]]

    tools.compare(p1, p2)
  }
}

多重限定

A和B爲T上界

class A

class B extends A

class C extends B

/*
trait A

trait B

class C extends B with A // 動態混入
*/

// 多重 上邊界  T類型必須同時是A和B類型的子類型【並且】
class E[T <: A with B](t:T)

object E{
  def main(args: Array[String]): Unit = {
    val e1 = new E[C](new C)
  }
}

A和B爲T下界

class A

class B extends A

class C

class D extends C

class E[T >: B with D](t: T) // T 類性是B類性或C類型父類型

object E {
  def main(args: Array[String]): Unit = {

    val e1 = new E[A](new A) // ok

    val e2 = new E[B](new B) // ok
    val e3 = new E[C](new C) // ok

    val e4 = new E[D](new D) //OK
  }
}

同時擁有上界和下界,並且A爲下界,B爲上界,A爲B的子類,順序不能顛倒

class A

class B extends A

class C extends B


class D[T >: C <: A](t: T)

object D {
  def main(args: Array[String]): Unit = {
    val d = new D[B](new B)
  }
}

視圖界定,即同時能夠滿足隱式轉換的A和隱式轉換的B (略)

def say[T <% A <% B](v:T):Unit={
  println(v)
}
trait A{}
trait B{}

+A 協變 [+T]

C[T1]是 C[T]的子類

// dog[T1] 是 animals [T]子類
// Convariant[T1] ---> Convariant[T] 的子類

class Animals

class Dog extends Animals

class A[+T]

object Dog {
  def main(args: Array[String]): Unit = {
    // 協變
    val a = new A[Dog]()

    val a2: A[Animals] = a  // 父子關係 A[Dog] extends A[Animals]
  }
}

// java
// Dog ---> Animals
// List<Dog> ---> List<Animals>

-A 逆變 [-T]

C[T] 是 C[T1]的子類

class Covariant[-T](t:T){}
val cov = new Covariant[Animal](new Animal("動物"))
val cov2:Covariant[Dog] = cov

A 不變 [T]

C[T] 與 C[T1]不相關

class Animals2

class Dog2 extends Animals2

class A2[-T]

object Dog2 {
  def main(args: Array[String]): Unit = {
    // 逆變
    val a = new A2[Animals2]()

    val a2: A2[Dog2] = a // 父子關係  A[Animals]  extends A[Dog]
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章