scala中的隱士轉換操作
- 隱士轉換的意義
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> 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(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
隐式转换的发生时机:
1、调用某个函数,但是给函数传入的参数类型,与函数定义的签名不匹配。
2、使用某个类型对象,调用某个方法,而这个方法并不存在于该类型时。
3、使用某个类型对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型与签名并不一致的时候。
网友评论