简介:
Scala提供的隐式转换和隐式参数功能,是非常有特色的功能。是Java等编程语言所没有的功能。它可以允许你手动指定将某种类型的对象转换成其他类型的对象,或是给一个类增加方法。通过这些功能,可以实现非常强大的功能。
1、隐式转换
隐式转换其核心就是定义一个使用 implicit 关键字修饰的方法,实现把一个原始类转换成目标类,这样你可以调用目标类中的方法,是不是很强大。隐式转换的方法需要定义在一个object中。
示例一:对第三方库类进行转化,让File类具备RichFile类中的read方法
import java.io.File
import scala.io.Source
object ExecFileDef {
//定义一个隐式转换的方法,实现把File转换成RichFile
implicit def file2RichFile(file: File) = new RichFile(file)
}
// 扩展file类
class RichFile(val file: File){
//读取数据文件的方法
def read():String={
Source.fromFile(file).mkString
}
}
object RichFile{
def main(args: Array[String]): Unit = {
//1、构建一个File对象
val file = new File("F:\\acc.txt")
//2、手动导入隐式转换
import ExecFileDef.file2RichFile
//此时的file已经被转化了, 可以使用read方法
val data: String = file.read
println(data)
}
}
示例二:对自己定义的类使用隐式转换,普通人成为大佬
class AveragePerson(val name: String)
class Mogul(val name: String) {
def come(): Unit = {
println("大佬 "+ name + " 来了,掌声想起,自带光环,疯狂撒钱!")
}
}
object TransformExec {
implicit def AveragePerson2Mogul(averagePerson: AveragePerson): Mogul = {
new Mogul(averagePerson.name)
}
def main(args: Array[String]): Unit = {
val mogul = new AveragePerson("橙子园")
mogul.come()
}
}
结果:
示例三:一个类隐式转换具有相同方法的类的情况
class A
class B(a: A) {
def readBook(): Unit ={
println("B读书")
}
}
class C(a: A){
def readBook(): Unit ={
println("C读书")
}
def writeBook(): Unit ={
println("C写书")
}
}
object BC{
//创建一个类转换为2个类的隐式转换
implicit def A2B(a: A)=new B(a)
implicit def A2C(a: A)=new C(a)
}
object C{
def main(args: Array[String]) {
//导包
//import BC._ 这会将AB类下的所有隐式转换导进来
//import BC.A2B 只导入A类到B类的的隐式转换方法
//import BC.A2C 只导入A类到C类的的隐式转换方法
import BC._
val a = new A
//由于B类与C类中都有readBook(),只能导入其中一个,否则调用共同方法时代码报错
//a.readBook()
//A类可以执行C类中的writeBook()
a.writeBook()
}
}
结果:
2、隐式参数
它是指在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的用implicit修饰的参数,即隐式值,并注入参数。隐式参数也需要定义在一个object中。
示例:隐式参数的使用,老板给员工发钱
object Company{
//注意:同一类型的隐式值只允许出现一次,否则会报错
implicit val name: String = "橙子园"
implicit val salary: Double = 100000.0
//再次出现会报错
//implicit val zzz: String="橙子猿"
}
class Boss {
//定义一个用implicit修饰的参数类型为String
//注意参数匹配的类型,它需要的是String类型的隐式值
def callName(implicit name: String): String={
name
}
//定义一个用implicit修饰的参数,类型为Double
//注意参数匹配的类型,它需要的是Double类型的隐式值
def getMoney(implicit money: Double): String={
money.toString
}
}
object Boss extends App{
//使用import导入定义好的隐式值,注意:必须先加载否则会报错
import Company.name
import Company.salary
val boss = new Boss
println(boss.callName + ":" + boss.getMoney)
}
结果: