隐式转换:在 Scala 编译器进行类型匹配时,如果找不到合适的类型就会编译失败,此时会在当前的环境中自动推导出合适的类型,从而完成编译。
在有些包含 by
的 Spark 算子中,其源码通常用 implicit
修饰某参数,implicit 指的就是隐式的意思。
隐式转换的作用:简化编程,调用方法时,不需要向隐式参数传参,Scala 会自动在其作用域范围内寻找隐式值,并自动传入。通过隐式转换,可以在不改变代码的情况下,扩展某个类的功能。
发生隐式转换的例子:
- 当方法中的参数与实际类型不一致时
- 当调用类中不存在的方法或属性时,会自动将对象进行隐式转换
不发生隐式转换的例子:
- 编译器在不发生隐式转换的情况下就编译通过,则可以不进行隐式转换
- 转换时存在二义性,不发生转换
举个Spark的例子:
def sortBy[K](
f: (T) => K,
ascending: Boolean = true,
numPartitions: Int = this.partitions.length)
(implicit ord: Ordering[K], ctag: ClassTag[K]): RDD[T] = withScope {
🌟 隐式函数
定义隐式函数时,需要使用柯里化的函数形式,所以这个不用传参,日常忽略便是。
🌟 隐式参数
普通方法或函数中的参数可以使用 implicit 关键字来声明称隐式参数,调用该方法时,编译器会自动寻找合适条件的隐式值。
- 同一个作用域中,相同类型的隐式值是能有一个
- 编译器按照隐式参数的类型去新招对象的隐式值,与隐式值的名称无关
- implicit 关键字必须放在隐式参数的开头
- 隐式参数优先于默认值
🌟 隐式类
Scala 2.10 后提供了隐式类,同样使用 implicit 声明隐式类,也是扩展类的功能,在集合中隐式类发挥着重要作用。
- 隐式类所带的构造参数有且仅有一个
- 隐式类必须被定义在“类”或“伴生对象”或“包对象”中,即隐式类不能是顶级的。
🌟 隐式解析
解析机制:首先会在当前代码作用域下查找隐式实体(包括方法、类、对象),如果第一条规则查找隐式实体失败,会继续查找隐式参数的类型的作用域里查找,类型的作用域是指与该类型相关联的全部伴生对象以及该类型所在包的对象。
🌟 隐式操作规则
- 标记规则:只有使用 implicit 关键字表示的部分才是隐式的
- 作用域规则:插入的隐式转换必须是单一标示符的形式处于作用域中,或与源/目标类型关联在一起
- 无歧义规则:不能存在多个隐式转换使编译通过
- 单一调用规则:不能重复嵌套使用隐式转换
- 显示操作优先原则:编译正常时,不进行转换
❤️ END ❤️