隐式转换
-
隐式参数
当函数的参数定义为implicit时,调用函数时可以缺少隐式参数,编译器会在作用域中寻找隐藏式值并作为确实的参数传入
def echo(implict content: String) = print(name) implict content = "kitty" //隐式值 cat // 输出: kitty
如果作用域内有多个隐式值,编译器将无法确定使用哪个隐式值而报错:ambiguous implicit values
-
类型隐式转换
类型隐式转换主要在以下两种场景中使用
- 当类型不匹配时,如表达式要求的类型是B,类型A不匹配,编译器会寻找隐式方法 A => B, 如果存在隐式方法,则会调用隐式方法将A转换为B
implicit def intToString(x : Int) = x.toString def printString(s: String) = print(s) printString(10) //如果没有隐式方法intToString,编译器会报type mismatch错误
- 当调用类不存在某种方法,通过隐式转换可以使转换后的类型存在该方法时
class HealthTiger { def eatEveryThing() = print("eat everything") } class SickTiger implicit def cure(a: SickTiger) = {new HealthTiger} new SickTiger().eatEveryThing() //编译器通过cure隐式转换,将SickTiger转换为HealthTiger
- 当类型不匹配时,如表达式要求的类型是B,类型A不匹配,编译器会寻找隐式方法 A => B, 如果存在隐式方法,则会调用隐式方法将A转换为B
-
隐式类
Scala 2.10之后提供隐式类, 与2中的隐式转换相比,可以理解为将隐式转换的查找扩大到了隐式类的构造函数
object Tiger { implicit class HealthTiger(val tiger : SickTiger){ //隐式类 def eatEveryThing() = print("eat everything") } } class SickTiger import Tiger._ println(new SickTiger().eatEveryThing)
使用隐式类的限制:
primary构造函数中,参数只能有一个
隐式类必须被定义在类,伴生对象和包对象中
-
查找隐式对象(隐式值,隐式方法,隐式类)的作用域有以下几部分
当前代码作用域
-
类型的作用域
如:T with A with B with C 作用域:T、A、B、C的伴生对象
-
类型参数和类型参数的类型
List[String]的隐式搜索会搜索List的伴生对象和String的伴生对象
如果T是一个单例类型a.T,作用域包括对象a
内部类型S#T,S和T的作用域