有时候咱们看scala代码的时候,会发现明明没有这个类的类型或者函数,甚至是没有这个类,编译器不只没有报错,程序还能够正常运行,其实这里就用到了scala的隐式转换。函数
当咱们调用一个对象的方法的时候,可是这个对象并无这个方法,此时就会触发隐式转换,会把这个对象偷偷的转换为具备这个方法的对象。
好比下面的例子,小鸡能够走路也能够跑,可是它也想像小鸟同样飞,可是它有没有这个功能。咱们能够在不对小鸡整改的基础上,引入ChickenImplicit,让小鸡能够隐式的调用Bird的fly方法,让它能够像小鸟同样飞。scala
object ImplicitDemo1 { def main(args: Array[String]): Unit = { import ChickenImplicit._ val chicken = new Chicken() chicken.work() chicken.run() // 隐式转为Bird,并调用Bird的fly方法 chicken.fly() } } class Chicken() { def work(): Unit = { println("小鸡在走") } def run(): Unit = { println("小鸡在跑") } } class Bird { def fly(): Unit = { println("小鸟在飞") } } object ChickenImplicit { implicit def chicken2Bird(c: Chicken): Bird = new Bird() }
上面是额外的定义ChickenImplicit,可是有时候咱们能够直接在同一个类里定义,这样局不用加import,具体用哪一种仍是要看实际场景。code
object ImplicitDemo2 { def main(args: Array[String]): Unit = { val chicken = new Chicken2() chicken.work() chicken.run() // 隐式转为Bird,并调用Bird的fly方法 chicken.fly() } implicit def chicken2Bird(c: Chicken2): Bird2 = new Bird2() } class Chicken2() { def work(): Unit = { println("小鸡在走") } def run(): Unit = { println("小鸡在跑") } } class Bird2 { def fly(): Unit = { println("小鸟在飞") } }
好比咱们要调用方法,打印咱们传递的参数,咱们是这样写的:对象
def main(args: Array[String]): Unit = { printInfo1("aaa") // aaa } def printInfo1(str: String): Unit = { println(str) }
若是咱们调用方法的时候,若是不想传递参数,咱们能够这样:
在方法里指定默认值ci
def main(args: Array[String]): Unit = { printInfo2("bbb") // bbb printInfo2() // default } def printInfo2(str: String = "default"): Unit = { println(str) }
若是经过隐式参数,那咱们就能够这样:
这里的方法不加括号也是能够的。因为是经过类型来匹配隐式值的,因此在一个做用域中,同一个类型只能有一次,而且他的优先级高于默认的,因此没有传递参数的时候,打印的implicit。作用域
def main(args: Array[String]): Unit = { implicit val str: String = "implicit" printInfo3("ccc") // ccc printInfo3() // default printInfo3 // implicit } def printInfo3(implicit str: String = "default"): Unit = { println(str) }
当咱们须要隐式转换的时候,咱们就须要用implicit
关键字。
隐式转换的时候,他会先全局的查找是否有匹配的方法或者参数,若是没有再考虑隐式转换。
因为隐式参数是根据类型的,因此同一做用域不能定义多个同一个类型的,而且默认值是优先于默认的。编译器