Implicit
隐式参数
定义的方法里包含一个隐式参数,调用的时候,会自动在调用的scope里查找对应类型(这里为Int)的变量,然后自动传入。
object Playground {
def main(args: Array[String]): Unit = {
def foo(x: Int)(implicit y: Int): Int = x + y
implicit val p: Int = 3 // 隐式变量
println(foo(2)) // print 5
}
}
隐式方法
当变量赋值时,如果两边的类型不一致,scala会自动地在调用的scope里查找是否存在隐式方法(或者当前类的伴生对象中查找),能够将右边的类型转为左边的类型,如果存在,就会自动调用(隐式转换),否则会报错。
object Playground {
def main(args: Array[String]): Unit = {
implicit def int2Str(v: Int): String = v.toString
var str = "aa"
str = 1
println(str)
}
}
隐式类
可以通过定义隐式类的手段,扩展一个已有的类,当调用时,如果scala在类中找不到方法,会去看有没有隐式类(当前类的伴生对象中查找,或当前的scope),将当前类转为隐式类之后,就可以调通目标方法,如果有,就会自动做隐式转换,否则会报错。
object Playground {
def main(args: Array[String]): Unit = {
case class A()
implicit class ShowOps(a: A) {
def show(): Unit = println("This is an implicit show method")
}
A().show() // 相当于ShowOps(A()).show()
}
}
Rules
- Only trigger by error
- Only once match
- Only do once
Context Bound
def g[A : B](a: A) = h(a)
def g[A](a: A)(implecit ev:B[A]) = h(a)
Type Class
object TypeClass extends App {
case class StudentId(id: Int)
case class StaffId(id: Int)
case class Score(s: Double)
trait Printer[A] {
def getString(a: A): String
}
object Printer{
implicit val studentPrinter: Printer[StudentId] = (a: StudentId) => s"StudentId: ${a.id}"
implicit val staffPrinter: Printer[StaffId] = (a: StaffId) => s"StaffId: ${a.id}"
implicit val scorePrinter: Printer[Score] = (a: Score) => s"Score: ${a.s}"
}
def show[A](a: A)(implicit printer: Printer[A]): String = printer.getString(a)
implicit class ShowOps[T](v: T) {
def show()(implicit printer: Printer[T]): String = printer.getString(v)
}
val studentId = StudentId(25)
println(show(studentId))
studentId.show()
val staffId = StaffId(12)
println(show(staffId))
staffId.show()
val score = Score(94.2)
println(show(score))
score.show()
}