隐式转换
1:隐式转换
主要应用在方法功能扩展和类型转换。
-
说明
scala提供的能够将一种类型根据需要,自动转化成其他类型的操作方式,进而可以让原有的类型具备其没有的功能,丰富现有api,而不会对原有的代码造成过多的污染。
这一点是scala程序非常优秀的一点设计,是java等其它语言所不具备的能力。其实在前面的视图界定案例中,视图界定就采用的是隐式转换将Int类型转化成为了RichInt,而RichInt扩展了Comparable接口,自然可以进行比较了。
这背后是通过一个叫做隐式转换函数的结构来时实现的。
-
隐式转换函数
现在有这样一个需求:
val x:Int = 3.5
要求这个赋值的变量,编译通过,显然正常情况下是不可以的,但是在scala中一切皆有可能,就需要用到隐式转换,本质是隐式转换函数。
隐式转换函数就是在普通的函数前添加一个关键字implicit,即可完成。一般的结构为
implicit def source2Target(source:Source):Target = { source ---> target 操作 }
这样,变量source就会在自己的作用域范围内自动的搜索是否有这样的隐式转换,如果有,则自动完成类型转换或者加强。
implicit def double2Int(d:Double):Int = d.toInt val a:Int = 3.5 println("a=" + a)
2: 利用隐士转换丰富现有类库的功能
利用隐士转换丰富现有类库的功能,举例说明,通过java.io.File来读取一个文件中的内容,但是File没有read的功能,如何能做到让File也具备流的读写功能?
在scala中的答案就是,隐式转换!
def main(args: Array[String]): Unit = {
val file = new File("E:/data/hello.txt")
file.read().foreach(println)
}
implicit def file2RichFile(file:File):RichFile = new RichFile(file)
//将file最后要转化为RichFile,才能具备read的功能
class RichFile(file:File) {
def read() = Source.fromFile(file).getLines()
}
3:引入隐士转换
当开发出一个隐式转换函数时,该如何使用呢?
最简单的其实就是,只要在要转换的变量的作用域内能够访问的到,即可进行自动转换,不需要人工干预。
在同一个文件中定义的隐式转换,不需要做任何的干预,但是如果要导入其它类中定义的隐式转换,要想在本类中使用,就必须要向导包一样导入。只要在其作用域到导入,即可。同时这个导入的隐式转换因为和导包一样,也不存在对原有类的结构发生入侵。
我们在导入的时候,我们倾向于导入到最靠近变量的部分。越靠近变量,其作用域范围越小,影响越小。
object _03ImplicitOps {
def main(args: Array[String]): Unit = {
import _02ImplicitOps._
val file = new File("E:/data/hello.txt")
file.read().foreach(println)
}
}
4:隐式转换参数
一个函数的参数被implicit修饰,称该参数为隐式转换参数,这个隐式转换参数在传递的时候,可以传,有时候也可以不用传。
def main(args: Array[String]): Unit = {
val list = List(3, -3, 0, -8, 45, 4)
list.foreach(println)
println("---------------")
implicit val ord = new Ordering[Int](){
override def compare(x: Int, y: Int) = {
y.compareTo(x)
}
}
//显示的传递隐式转换参数
list.sorted(ord).foreach(println)
println("-------隐式传递---------")
//隐式传递隐式转换参数
list.sorted.foreach(println)
}
说明:隐式转换参数,可以显示的指定,也可以隐式的指定,如果是隐式指定,就需要让该变量在其作用域内访问到被implicit关键字修饰的相关变量,自动进行赋值。