概述
在scala中的implicit意味着可以将一种数据类型自动转换为另一种数据类型,或者在方法调用时某些参数可以自动传递给方法。
隐式类型转换(implicit conversion)
隐式类型转换简单的说,如果在类C的对象o上调用方法m,并且该类不支持方法m,那么Scala将寻找从C到支持m的隐式转换。
String类型的隐式转换
scala.Predef定义了String类型的2种隐式转换方式:
- String转换为WrappedString
- String转换为StringOps
//scala-library_2.12.3
/** @group conversions-string */
@inline implicit def augmentString(x: String): StringOps = new StringOps(x)
/** @group conversions-string */
implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null
String隐式转换示例:
object ImplicitLearning extends App{
val s:String = "Mark"
println(s.take(2)) //控制台输出“Ma”
}
Stirng不支持taken方法,但是StringOps支持,并且在predef定义了从String到StringOps的隐式转换,所以这里会将String类型的对象s自动转换StringOps类型。
自定义隐式类型转换
object ImplicitLearning extends App{
val s:String = "Mark"
case class HiString(s:String){
def sayHi(): Unit = {
println("Hi " + s)
}
}
//convert String to HiString
implicit def argumentString(s:String): HiString = HiString(s)
s.sayHi() //控制台输出“Hi Mark”
}
隐式参数(implicit parameters)
一个方法可以有一个隐式参数列表,通过在该参数列表的开头用implicit关键字标记。如果这些参数没有像往常一样在方法调用时传递给方法,scala会寻找该参数类型的一个隐式值,如果找得到的话,自动传递给方法。
object ImplicitLearning extends App{
case class HiString(s:String){
def sayHi(): Unit = {
println("Hi " + s)
}
}
//this method has two argument list
//the second one is the implicit argument list
//one method has two argument list, which is called curying.
def doItAFewTimes(numTimes: Int)(implicit hiString: HiString): Unit = {
for(i <- 1 to numTimes){
hiString.sayHi()
}
}
//this is an implicit HiString value available
implicit val hiString = new HiString("Biff")
doItAFewTimes(5)
}
输出结果为
Hi Biff
Hi Biff
Hi Biff
Hi Biff
Hi Biff
如果你没有为隐式参数列表的所有参数提供implicit value,则你应该在方法调用时显式提供参数。
val hiString = new HiString("Biff")
doItAFewTimes(5)(hiString)
//It is equal to the above:
//implicit val hiString = new HiString("Biff")
//doItAFewTimes(5)
参考:
scala doc -implicit parameters