先来看个demo
package com.peng.implicit_demo
import java.io.File
import scala.io.Source
object MyPredef {
implicit def file2RichFile(file: File): RichFile = new RichFile(file)
}
class RichFile(file: File) {
def read(): String = {
val fis = Source.fromFile(file)
fis.mkString
}
}
object RichFile {
def main(args: Array[String]): Unit = {
//1.构建一个File对象
val file = new File("F:\\learnbigdata\\spark\\base\\testdata\\rawdata\\test.txt")
//2.手动导入隐式转换
import MyPredef.file2RichFile
//3.调用read方法
val data: String = file.read()
//4.打印结果
print(data)
}
}
从上面可以看到,在手动导入隐式转换后,file对象就有了read方法.在我看来,其实在导入隐式转换后,file对象就像被包装类包装了一样,获得了增强的功能.
再来看看其他例子
package com.peng.implicit_demo
class Man(val name: String)
class SuperMan(val name: String) {
def heat(): Unit = print("超人打怪兽")
}
object SuperMan {
//隐式转换
implicit def man2SuperMan(man: Man): SuperMan = new SuperMan(man.name)
def main(args: Array[String]): Unit = {
//实例化的时候,会把man注入man2SuperMan方法,得到增强后的实例
val hero = new Man("hero")
//man具备了SuperMan的方法
hero.heat
}
}
一个类可以隐式转换成具有相同方法的多个类
package com.peng.implicit_demo
//一个类隐式转换成具有相同方法的多个类
class C
class A(c: C) {
def readBook(): Unit = {
println("A说:好书好书...")
}
}
class B(c: C) {
def readBook(): Unit = {
println("B说:看不懂...")
}
def writeBook(): Unit = {
println("B说:不会写...")
}
}
object AB {
//创建一个类转换为2个类的隐式转换
implicit def C2A(c: C) = new A(c)
implicit def C2B(c: C) = new B(c)
}
object B {
def main(args: Array[String]) {
//导包
//1. import AB._ 会将AB类下的所有隐式转换导进来
//2. import AB.C2A 只导入C类到A类的的隐式转换方法
//3. import AB.C2B 只导入C类到B类的的隐式转换方法
import AB._
val c = new C
//由于A类与B类中都有readBook(),只能导入其中一个,否则调用共同方法时代码报错
//c.readBook()
//C类可以执行B类中的writeBook()
c.writeBook()
}
}
再来看看隐式参数转换
package com.peng.implicit_demo
//隐式参数转换
object Company {
//在object中定义隐式值
//注意:同一类型的隐式值只允许出现一次,否则会报错
implicit val xxx = "zhangsan"
implicit val yyy = 10000.00
//implicit val zzz="lisi"
}
class Boss {
//定义一个用implicit修饰的参数 类型为String
//注意参数匹配的类型,它需要的是String类型的隐式值
def callName(implicit name: String): String = {
name + " is coming !"
}
//定义一个用implicit修饰的参数,类型为Double
//注意参数匹配的类型,它需要的是Double类型的隐式值
def getMoney(implicit money: Double): String = {
" 当月薪水:" + money
}
}
object Boss extends App {
//使用import导入定义好的隐式值,注意:必须先加载否则会报错
//这步操作,相当于对callName和getMoney中的相同数据类型的参数赋值
import Company.xxx
import Company.yyy
val boss = new Boss
println(boss.callName + boss.getMoney)
}