大家都知道:1 to 10
等价于1.to(10)
。其实,Scala 中的Int 类型是没有to这个方法的,那为什么还能调用to方法?其实是编译器偷偷地帮我们完成Int->RichInt的转换,这个就是隐式转换。隐式转换可以丰富现有类库的功能。
在REPL中键入:implicits -v
查看编译器默认导入的隐式转换。笔者使用的Scala版本为2.11.8。
第一个隐式转换的例子
//从设计模式的角度来看,隐式转换包含了装饰者模式。
class RichFiles(file : File){
def read = Source.fromFile(file).mkString
}
object Context {
/**
* 目标类:File
* 装饰类:RichFile
*/
implicit def File2RichFile(file: File) = new RichFiles(file)
}
object Implicit_{
def main(args: Array[String]) {
//导入隐式转换
import Context.File2RichFile
val contents = new File("c://word.txt").read
println(contents)
}
}
隐式参数
object implicitContext{
//scala 如果参数用implicit修饰,那么方法的执行会在作用域查找与该参数{类型相同}的参数,并把它传入方法中
implicit val valueImplicit: Int = 33
}
object ImplicitValue {
def fun(x: Int)(implicit y: Int = 10)=x * y
def main(args: Array[String]): Unit = {
import implicitContext._
println(fun(2))
}
}
结果为66
Context Bounds
//如果是上下文界定,必须存在一个隐式值(隐式参数)
class Pairs[T : Ordering](f: T,s: T){
def bigger(implicit ord: Ordering[T]) = if(ord.compare(f,s)>0) f else s
}
object OrderingDemo {
def main(args: Array[String]) {
val p = new Pairs("ABC","BCD")
println(p.bigger)
}
}
View Bounds
//如果是View Bounds,则必须存在隐式转换函数
class MrsRight[T](f: T,s: T) {
def choose(implicit ord: T => Ordered[T]) = if(f > s) f else s
}
//2.11之后view bounds 被舍弃了
//class MrsRight[T <% Ordered[T]](val f: T,val s: T){
// def choose = if(f > s) f else s
//}
class Girl(val name: String,val faceValue: Int){
}
//定义隐式转换函数
object RightContext{
implicit def girl2OrderedGirl(f: Girl) = new Ordered[Girl]{
override def compare(that:Girl) = if(f.faceValue > that.faceValue) 1 else -1
}
}
object MissRight{
def main(args: Array[String]) {
val g1 = new Girl("yuihatano",40)
val g2 = new Girl("gaoyuanyuan",45)
val m = new MrsRight(g1,g2)
//导入隐式转换
import RightContext.girl2OrderedGirl
println(m.choose.name)
}
}