`

scala学习笔记(十三):implicit 详解

 
阅读更多

implicit 可分为三种 隐式参数 隐式转换类型 隐式调用函数

1、隐式参数
implicit参数都是定义在方法最后,修饰implicit表示该组参数是隐式参数。一个方法只会有一个隐式参数列表,置于方法的最后一个参数列表。如果方法有多个隐式参数,只需一个implicit修饰即可

//使用隐式参数的方式 需要在外部定义一个Comparator[A]类型的变量
  def maxThrid[A](first: A, second: A)(implicit cp: Comparator[A]) = {
    if (cp.compare(first, second) > 0) first else second
  }

//使用implicitly方法 
  //implicitly是在Predef.scala里定义的,它是一个特殊的方法,编译器会记录当前上下文里的隐式值,而这个方法则可以获得某种类型的隐式值
  def maxOne[A: Comparator](first: A, second: A) = {
    val cp = implicitly[Comparator[A]]
    if (cp.compare(first, second) > 0) first else second
  }

  //在内部定义函数并声明隐式参数,这种做法只是把外部方法的隐式参数隐藏了,放到内部嵌套函数上
  def maxTwo[A: Comparator](first: A, second: A) = {
    def inner(implicit cp: Comparator[A]) = cp.compare(first, second)
    if (inner > 0) first else second
  }

 def main(args: Array[String]) {
    //隐式参数
    implicit val cInt = new Comparator[Int] {
      override def compare(o1: Int, o2: Int) = o1 - o2
    }
    println(maxOne(2, 3))
    println(maxTwo(4, 1))
  }

 2、隐式转换类型

  把变量转换成我们预期想要的类型

   //隐式地转换类型
    implicit def doubleToInt(a:Double):Int = a.toInt
    //这里3.5就会转换成int类型,如果没有上面的隐式转换就会编译出错
    val i:Int = 3.5
    println(i)

 3、隐式调用函数

就是我们使用的对象可能不存在某个方法,但是另外一个对象存在,那么我们隐式的转换成那个存在某个方法的对象,来进行操作

class Anime{
  def say = println("hello!")
}

class Dog

object ImplicitAnime{
  implicit def dogToAnime(d:Dog):Anime = new Anime 
}


//隐式调用函数 Dog并没有say函数,但是通过dogToAnime隐式方法转换成Anime实例就存在say方法
//编译器通过隐式转换将对象转换成具有这个方法的对象
val d = new Dog
import com.aralbox.scala.study42.ImplicitAnime._
d.say

 4、下面是更复杂的例子

package com.aralbox.scala.study42

object implicitType {
  def main(args: Array[String]) {
	  val p = Person("Tom", 32)
	  //scala2.8 加入了def implicitly[T](implicit e: T): T = e 方法
	  val s = implicitly[Show[Person]].show(p)
	  println(s)
	  //si指定给implicitly方法表明si自动去查找隐式参数 
	  //ss指定ShoutyStringShow方法,因为ShoutyStringShow方法也是返回Show[String]所以匹配ss参数类型
	  val s1 = Person.personShow(si = implicitly, ss = Show.ShoutyStringShow ).show(p)
	  println(s1)
  }
}

trait Show[T] {
  def show(t: T): String
}

object Show {
  //隐式转换Show[Int]
  implicit def intShow: Show[Int] = new Show[Int] {
    def show(i: Int): String = i.toString
  }
  //隐式转换Show[String]
  implicit def strShow: Show[String] = new Show[String] {
    def show(s: String): String = s
  }

  def ShoutyStringShow: Show[String] = new Show[String] {
    def show(s: String): String = s.toUpperCase()
  }
}

case class Person(name: String, age: Int)

object Person{
  //隐式转换Show[Person]  
  //personShow里面有2个隐式参数Show[String]和Show[Int]
  //它会发现在Show对象里面存在Show[String]和Show[Int]隐式参数定义
  implicit def personShow(implicit ss:Show[String], si:Show[Int]):Show[Person] = new Show[Person]{
    def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
  }
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics