Skip to content

Implicit Class

Song Kun edited this page Dec 31, 2017 · 1 revision

基本用法

Scala 2.10 引入的特性,使用 implicit class 声明的类即为隐式类,在隐式类所在的作用域中,该类的 主构造函数 可以用于隐式转换。

例如,有如下隐式类:

implicit class IntWithTimes(x: Int) {  
  def times[A](f: => A): Unit = {  		
    def loop(current: Int): Unit =
      if (current > 0) {
        f
        loop(current - 1)
      }
  		
    loop(x)
  }
}

如上,定义了隐式类 IntWithTimes,该类有方法 times,该方法接受一个函数,并执行该函数 current 次,可以如下使用:

5 times {
      val x = 10;
      println("Hi " + x)
    } 
  • 因为 IntWithTimes 隐式类在当前作用域中,所以 Int 值 5 会按照 IntWithTimes 的主构造函数,隐式转为 IntWithTimes 类的实例,然后使用 case 函数调用其 times 方法
  • 输出 5 个 Hi 10

限制

隐式类的使用有如下限制:

  • 必须在 trait/class/object 内部定义:

    object Helpers {
      implicit class RichInt(x: Int) // OK!
    }
    implicit class RichDouble(x: Double) // BAD!
  • 其构造函数只能接受一个 non-implicit 参数(其实可以创建有多个 non-implicit 参数的隐式类,但这些类无法用于):

    implicit class RichDate(date: java.util.Date) // OK!
    implicit class Indexer[T](collecton: Seq[T], index: Int) // BAD! 无法用于隐式转换
    implicit class Indexer[T](collecton: Seq[T])(implicit index: Index) // OK!
  • 同一作用域中,不能有任何与隐式类同名的 method member 或者 object,这意味着隐式类不能是 case class(因为 case class 会自动创建同名的 case object):

    object Bar
    implicit class Bar(x: Int) // 不能与 object 同名
    
    val x = 5
    implicit class x(y: Int) // 不能与 member 同名
    
    implicit case class Baz(x: Int) // 不能是 case class
Clone this wiki locally