前言
目的
(悄无声息、偷偷摸摸)增强已有的方法、函数、类
隐式转换是把双刃剑,用的好,增加代码健壮性,用的不好,代码执行流程难以理解。
隐式转换有三种
- 隐式参数
- 隐式类型转换
原有个A类型,现在转换成B类型,B是从A中拿到的,B要对A的功能进行增强,增强过程“悄无声息”,写代码时候感知不到。
- 隐式类
其中隐式参数和隐式类型转换这两种为重点
三种类型隐式转换的实现
1.隐式参数
方法/函数的参数可以使用implicit来修饰
一个参数的隐式转换
object ImplicitApp {
def main(args: Array[String]): Unit = {
implicit val word = "欢迎学习spark"
implicit val word2 = 123
/**
* 如果函数内的参数使用implicit,调用函数时
* 调用是 参数如果不添加,会从上文去寻找 implicit string类型的变量
* 例如 sayHello2 隐式参数为String类型,定义的word2为Int型就会忽略
* 但是 string类型的变量只能有一个(不符合类型的隐式值不会有影响,只会去找符合参数类型的隐式值),否则会有下面的报错信息
* --------------------------------
* both value word2 of type String
* and value word of type String
* match expected type String
* sayHello2
* --------------------------------
*/
sayHello(word)
sayHello2
def sayHello(msg: String): Unit = println(s"普通输出:${msg}")
def sayHello2(implicit msg: String = "默认值"): Unit = println(s"隐式转换输出:$msg")
}
}
2.隐式类型转换
需求:如何为一个已存在的类,添加一个新方法?
在java中可以使用Proxy 来解决
Scala可以用implict来完成
object ImplicitApp {
def main(args: Array[String]): Unit = {
val superman = new Superman("钢铁侠")
superman.fly()
//如何定义隐式转换函数,将人变成超人
//定义好 implicit后,scala就会自动生成隐式转换
//公式 implict def xToy (普通的X):牛逼的Y = new 牛逼的Y(.....)
implicit def manToSuperman(man:Man):Superman = {
new Superman(man.name)
}
val man = new Man("绿巨人")
man.fly()
}
}
//普通人无任何特意功能
class Man(val name:String)
//超人有特异功能,可以飞
class Superman(val name:String){
def fly():Unit = {
println(s"$name can fly")
}
}
3.隐式类
import java.io.File
import scala.io.Source
object ImplicitApp {
def main(args: Array[String]): Unit = {
println(2.add("4"))
/**
* 首先scala中的Int类型是不存在add方法的
* 我们定义了一个Int类型的隐式类,所有Int类型都会加强方法
* 因此,在这里scala Int类型都会增强出add方法
*/
implicit class Cal(x: Int) {
def add(a: String) = s"隐式类拼接:调用值为:$a 函数输入值为:${x}"
}
/**
* 同上面的道理,java的File方法没有read方法
* 我们定义一个File类型的隐式类,就会为所有File类新增一个 read方法
*/
val file = new File("data/file.txt")
println(file.read)
implicit class FileEnhance(file: File) {
def read = Source.fromFile(file.getPath).mkString
}
}
}