隐式转换和隐式参数是 scala 非常有特色的功能,也是Java等其他编程语言没有的功能。
利用隐式转换 可以很方便地来丰富现有类的功能,在编写Akka并发编程、Spark SQL、Flink 等程序时 都会看到隐式转换和隐式参数的身影;但其实现方式有点绕,不太容量理解。
以下通过 Demo 来说明:
实现隐式转换方法的 Demo:
目的:File 类本身没有 read 方法,希望代码看起来像 File 有能直接调用的 read 方法一样;
实现步骤:1)定义隐式转换方法 File2RichFile (RichFile 含有 read 方法);2)导入隐式转换方法。
然后即可实现目的。
原理:隐式转换方法的关键在于入参类型和出参类型, 与方法名无关;
代码表面上是入参类型的对象 调用了 某方法,实际底层是出参类型的对象调用的那个方法,因为 入参类型的对象 被隐式转换成了 出参类型的对象。
具体就此 Demo 来说,File 调用 read 方法时,编译器发现此类本身并没有此方法,则会寻找并调用以 File 类为入参类型的隐式转换方法 File2RichFile,于是背地里 file 对象就被悄悄转成了 richFile 对象,richFile 有 read 方法的定义,于是编译通过。
class RichFile(file: File) {
def read() = {
Source.fromFile(file).mkString
}
}
// 手动使用import来导入隐式转换:
// 1) 在object中定义隐式转换方法(使用implicit)
// 2) 在需要用到隐式转换的地方,引入隐式转换(使用import)
// 3) 自动调用隐式转化后的方法
// object RichFile {
// implicit def File2RichFile(file:File): RichFile = new RichFile(file)
// }
//
// def main(args: Array[String]) {
// val file = new File("./data/1.txt")
//
// import RichFile.File2RichFile
//
// println(file.read())
// }
// 在scala中,如果在当前作用域中有隐式转换方法,会自动导入隐式转换。
// 自动导入隐式转换方法
// 此方法的关键在于入参类型和出参类型, 方法名无所谓
// 有此方法时, 如果入参类型的对象调用了自身没有的方法, 编译器则会尝试调用出参类型的方法
implicit def File2RichFile(file:File): RichFile = new RichFile(file)
def main(args: Array[String]) {
val file = new File("./data/1.txt")
println(file.read())
}
隐式参数的 Demo, 原理与隐式转换类似,只是隐式参数调用处有显式指明 "implicit",则调用 quote 方法时不必传这种参数,但也可显式传参,编译器将优先取显式传参(编译器的优先级为: 传值 >隐式值>默认值):
def quote(msg:String)(implicit delimiter:(String, String)) = {
delimiter._1 + msg + delimiter._2
}
// 和隐式转换一样,可以使用import手动导入隐式参数
// object ImplicitParam {
// implicit val DELIMITER = ("<<<", ">>>")
// }
//
// def main(args: Array[String]) {
// import ImplicitParam.DELIMITER
//
// println(quote("metacognition"))
// }
// 自动隐式转换参数
// 如果在当前作用域定义了隐式值,会自动进行导入
// 参数名无所谓,调用 quote 方法时 隐式入参类型为 (String, String),编译器即会寻找并使用此类型的隐式参数
implicit val DELIMITER = ("<<<", ">>>")
def main(args: Array[String]) {
println(quote("metacognition"))
}
本文通过实例详细解析Scala中的隐式转换和隐式参数功能,包括如何定义及使用这些特性来增强类的功能,特别是在Akka并发编程、SparkSQL等场景的应用。
2716

被折叠的 条评论
为什么被折叠?



