为现有的类库增加功能的一种方式,用java的话,只能用工具类或者继承的方式来实现,而在scala则采用隐式转化的方式来实现。
● scala隐式转换可以把一个类的实例当作另一个类的实例,这样一来,通过在facade里隐式封装实例,无需修改原来的类,就可以将方法附着于对象上。这种技巧可以用于创建DSL。
● 在Predef对象里,scala定义了一些隐式转换,scala默认导入它们,这样的话,比如写1 to 3时,scala会隐式将1从Int转换为RichInt类型,然后调用to()方法
● scala一次至多应用一个隐式转换,在当前范围内,如果发现通过类型转换有助于操作、方法调用或类型转换的成功完成,就会进行转换,不再继续往外找。
A、位于源或者目标类型的companion object中的隐式函数
B、位于当前作⽤用域可以以单个标识符指代的隐式函数
额外说明:
A、如果代码能在不使用隐式转换的前提下通过编译,则不会使用隐式转换
B、编译器不会同时使用多个隐式转换
C、 存在二义性的隐式转换不被允许
A、必须定义在另外一个class/object/trait里头
B、构造器中只能带一个不是implicit类型的参数
C、作用域中不能有与隐式类类名相同的成员变量/函数名/object名
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) }
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") }
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) }
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) }
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 }
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 } }