//[T: Ordering]:說明存在一個隐式類型Ordering[T]
class Pair_Implicits[T: Ordering](val first: T, val second: T) {
//聲明一個隐式類型對象傳入函數
def bigger(implicit ordered: Ordering[T]): T = {
if (ordered.compare(first, second) > 0) first else second
}
}
//簡化上面的寫法
class Pair_Implicitly[T: Ordering](val first: T, val second: T) {
def bigger: T =
if (implicitly[Ordering[T]].compare(first, second) > 0) first else second
}
//進一步簡化
class Pair_Implicitly_Ordered[T: Ordering](val first: T, val second: T) {
def bigger: T = {
import Ordered._
if (first > second) first else second
}
}
//視圖界定寫法
class Pair_Implicitly_Ordered_View_Bounds[T <% Ordered[T]](val first: T, val second: T) {
def bigger = {
if (first > second) first else second
}
}
//隐式參數與隐式轉換
class Pair_Implicitly_With_Implicit_Parameters {
def bigger[T](a: T, b: T)(implicit ordered: T => Ordered[T]): T = {
if (a > b) a else b
}
}
class Boy(val name: String) {
override def toString: String = name
}
class RichBoy(val boy: Boy) {
def upper: String = boy.name.toUpperCase
}
//通過伴生對象進行隐式轉換
class Implicits_Boy(name: String) extends Boy(name)
object Implicits_Boy {
implicit def boy2RichBoy(boy: Boy): RichBoy = new RichBoy(boy)
}
abstract class Template[T] {
def add(x: T, y: T): T
}
abstract class SubTemplate[T] extends Template[T] {
def unit: T
}
object Context_Bounds_Internals {
//下面這兩個隐式導入二選一都生效,因為Ordered與Ordering内部定義了互相轉換的隐式導入方法
//若同時在,根據導入路徑短的有限,boy2Ordered對前三個類生效,boy2Ordering對後兩個類生效
implicit def boy2Ordered(boy: Boy): Ordered[Boy] = (that: Boy) => -boy.name.compareTo(that.name)
implicit val boy2Ordering: Ordering[Boy] = (x: Boy, y: Boy) => x.name.compareTo(y.name)
//隐式類
//有時候進行代碼重構,要增強他的某項功能同時又不想做太大的改動
//更多用的是隐式轉換,隐式類用的不多
implicit class EnhanceBoy(boy: Boy) {
def getName: String = boy.name
}
//定義隐式對象 定義方式:implicit object XXX
implicit object IntAdd extends SubTemplate[Int] {
def add(x: Int, y: Int): Int = x + y
def unit: Int = 0
}
implicit object StringAdd extends SubTemplate[String] {
def add(x: String, y: String): String = x concat y
def unit: String = ""
}
def main(args: Array[String]): Unit = {
//上下文界定中的隐式參數
//在每次上下文運作的執行個體對象中将具體的值注入到隐式參數中,而且注入的過程是自動的
println(new Pair_Implicits(new Boy("a"), new Boy("b")).bigger)
println(new Pair_Implicitly(new Boy("a"), new Boy("b")).bigger)
println(new Pair_Implicitly_Ordered(new Boy("a"), new Boy("b")).bigger)
println(new Pair_Implicitly_Ordered_View_Bounds(new Boy("a"), new Boy("b")).bigger)
println(new Pair_Implicitly_With_Implicit_Parameters().bigger(new Boy("a"), new Boy("b")))
/**
* Boy對象中并沒有getName方法 編譯器會在全局範圍内查詢比對的隐式類
* 在Context_Bounds_Internals導入的類中有EnhanceBoy接受Boy類型的類 會自動比對 、
* 使得Boy對象通過這種隐式的方法具有getName方法
*/
println(new Boy("zhangsan").getName)
/**
* 這裡沒有導入隐式對象
*
* 通過給Implicits_Boy類 建構一個伴生對象 在伴生對象内部定義一個隐式轉換的方法
*
* 執行順序:
* 1.搜尋Implicits_Boy有無upper方法
* 2.在上下文上搜尋(有無導入的隐式對象)
* 3.搜尋Implicits_Boy的伴生對象内有無隐式轉換 發現implicit關鍵 嘗試比對類型
* 例如這裡比對boy2RichBoy(boy: Boy) 傳回類型為RichBoy 在RichBoy中發現upper方法
*/
println(new Implicits_Boy("i am Implicits_Boy").upper)
//implicit m: SubTemplate[T]中 m是一個隐式對象就是實際在運作的對象
def sum[T](xs: List[T])(implicit m: SubTemplate[T]): T =
if (xs.isEmpty) m.unit
else m.add(xs.head, sum(xs.tail))
println(sum(List(1, 2, 3))) //6
println(sum(List("Scala", "Spark", "Kafka"))) //ScalaSparkKafka
}
}
輸出:
b
b
b
a
a
zhangsan
I AM IMPLICITS_BOY
6
ScalaSparkKafka