//[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