Scala提供的隐式转换的特性的作用,简单说就是:当Scala编译器进行类型匹配时,如果找不到合适的类型,那么隐式转换会让编译器在作用范围内自动推导出合适的类型,在代码重构设计上,可以避免冗余的代码,使得代码非常优雅。
使用场景一:隐式参数
scala> def sayHello(age: Int)(implicit name: String) = println("my name is:" + name + ",my age is:" + age) sayHello: (age: Int)(implicit name: String)Unit scala> implicit val name = "cyony" name: String = cyony scala> sayHello(25) my name is:cyony,my age is:25
sayHello函数有两个参数,其中name为隐式参数,在实际调用中不需要显示传入这个参数,但是在作用域范围内必须声明一个String类型的隐式变量,这样在调用的时候,会自动传入这个变量。PS:如果在同一个作用域内定义了两个同类型的隐式变量,则会有冲突。
隐式参数的作用域范围有两个:一种是当前作用域内可见的val或者var定义的隐式变量;一种是隐式参数类型的伴生对象内的隐式值。
scala> implicit val name1 = "cyony1" name1: String = cyony1 scala> sayHello(25) <console>:16: error: ambiguous implicit values: both value name of type => String and value name2 of type => String match expected type String sayHello(25) ^
使用场景二:类型匹配
scala> import scala.language.implicitConversions import scala.language.implicitConversions scala> implicit def int2Range(num : Int): Range = 1 to num int2Range: (num: Int)Range scala> def spreadNum(range: Range): String = range.mkString(",") spreadNum: (range: Range)String scala> spreadNum(5) res0: String = 1,2,3,4,5
上面所示,spreadNum函数签名是个Range类型的参数,但是传入的值是一个Int类型的,所以编译器在作用域内找到了int2Range隐式转换函数,自动将int转换为range对象来适配。
隐式转换的函数叫什么名字无所谓,因为实际调用中不会手动调用,但是如果需要使用隐式转换函数,需要import方式手动导入,才能被编译器寻找到。
使用场景三:类型增强
scala> class Man(val name: String) defined class Man scala> class SuperMan(val name: String) { | def fly = println("you can fly") | } defined class SuperMan scala> implicit def man2SuperMan(man: Man): SuperMan = new SuperMan(man.name) man2SuperMan: (man: Man)SuperMan scala> val cyony = new Man("cyony") cyony: Man = Man@63d3c9dc scala> cyony.fly you can fly
编译器在调用fly方法时,发现Man对象并没有这个函数,然后通过man2SuperMan隐式函数转换成SuperMan对象,进而调用他的fly函数,来实现类型增强功能。
或者可以通过隐式类的方式来实现相同的功能,代码如下:
scala> class Man(name: String) defined class Man scala> implicit class MyImplicitTypeConversion(val man: Man) { | def fly = println("you can fly") | } defined class MyImplicitTypeConversion scala> val cyony = new Man("cyony") cyony: Man = Man@7412a438 scala> cyony.fly you can fly
隐式转换的发生时机:
1、调用某个函数,但是给函数传入的参数类型,与函数定义的签名不匹配。
2、使用某个类型对象,调用某个方法,而这个方法并不存在于该类型时。
3、使用某个类型对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型与签名并不一致的时候。