一、简介
为现有的类库增加功能的一种方式,用java的话,只能用工具类或者继承的方式来实现,而在scala则采用隐式转化的方式来实现。
● scala隐式转换可以把一个类的实例当作另一个类的实例,这样一来,通过在facade里隐式封装实例,无需修改原来的类,就可以将方法附着于对象上。这种技巧可以用于创建DSL。
● 在Predef对象里,scala定义了一些隐式转换,scala默认导入它们,这样的话,比如写1 to 3时,scala会隐式将1从Int转换为RichInt类型,然后调用to()方法
● scala一次至多应用一个隐式转换,在当前范围内,如果发现通过类型转换有助于操作、方法调用或类型转换的成功完成,就会进行转换,不再继续往外找。
A、位于源或者目标类型的companion object中的隐式函数
B、位于当前作⽤用域可以以单个标识符指代的隐式函数
额外说明:
A、如果代码能在不使用隐式转换的前提下通过编译,则不会使用隐式转换
B、编译器不会同时使用多个隐式转换
C、 存在二义性的隐式转换不被允许
二、使用方式
1、定义转换类,以及隐式转换方法
2、scala 2.10 以后可以直接定义隐式类
A、必须定义在另外一个class/object/trait里头
B、构造器中只能带一个不是implicit类型的参数
C、作用域中不能有与隐式类类名相同的成员变量/函数名/object名
3、隐式参数
三、实例
1、隐式转化方法
package persia.demo
object Implicit {
def main(args: Array[String]): Unit = {
import java.util._
class DateHelper(number: Int){
def days(when: String): Date={
var date = Calendar.getInstance()
when match{
case "ago" => date.add(Calendar.DAY_OF_MONTH,-number)
case "from_now" => date.add(Calendar.DAY_OF_MONTH,number)
case _ => date
}
date.getTime()
}
}
//只要该方法在当前范围内存在(通过当前import可见或是位于当前文件)
//scala就会自动调用它,将int转换为DateHelper实例然后调用days方法
implicit def convertInt2DateHelper(number: Int) = new DateHelper(number)
val past = 2 days "ago"
println(past)
val appointment = 5 days "from_now"
println(appointment)
}
}
或者
class RichFile(val file:File){
def read = Source.fromFile(file.getPath()).mkString
}
object Context{
implicit def file2RichFile(f:File)= new RichFile(f)
}
object ImplicitDemo extends App{
import Context.file2RichFile
println(new File("f:\\create.sql").read)
}
2、隐式参数
object Context{
implicit val ccc:String = "implicit"
}
object Param{
def print(content:String)(implicit prefix:String){
println(prefix+":"+content)
}
}
object ImplicitDemo extends App{
Param.print("jack")("hello")
import Context._
Param.print("jack")
}
3、隐式类
object Context{
implicit def file2RichFile(f:File)= new RichFile(f)
implicit val ccc:String = "implicit"
implicit class Op(x:Int){
def add2 = x+2
}
}
object ImplicitDemo extends App{
import Context._
println(1.add2)
}
四、扩展
1、隐式转化扩展
class RichFile(val file:File){
def read = Source.fromFile(file.getPath()).mkString
}
object Context{
implicit def file2RichFile(f:File)= new RichFile(f)
}
object ImplicitDemo extends App{
import Context.file2RichFile
println(new File("f:\\create.sql").read)
}
2、隐式类扩展
import java.io.File
import scala.io.Source
object Helper{
implicit class FileEnhancer(f : File){
def read(file : File) = Source.fromFile(file.getPath).mkString
}
}
object Demo2 extends App{
import Helper._
val f = new File("your file path")
f.read
}
3、隐式参数扩展
import java.io.File
object Demo3 extends App{
//RichFile is already defined in Demo1.scala
def _read(f : File)(implicit file : File => RichFile){
f.read
}
}