【大纲】
【正文】
1.隐式转换
1.1.【结论】作用
已有A类,想在不改变A类的前提下,让A类拥有新的成员方法m(),即对A类进行增强
本质是新写个B类,让B拥有m(),通过隐式转换,将A类型对象自动转换为B类型对象,让A来使用B的m()
类似于java的装饰者模式
1.2.【结论】手动导入隐式转换方法
# 0.定义一个B类,让B拥有m()
class B(a:A){
def m() = println("m")
}
# 1.在任意单例类中,定义一个隐式转换方法a2b,可将A对象转为B对象
object C{
implicit def a2b(a:A) = new B(a)
}
# 2.创建A对象,使A对象调用m()
def main(args: Array[String]): Unit = {
import C.a2b // 手动导入隐式转换方法
val a = new A()
a.m() // 效果:编译器会先看A对象a没有m方法,但检测到有 隐式转换方法 会将a转成B对象b,调用b的m方法
}
示例
object ImplicitFunc {
class RichFile(file:File){
def read() = Source.fromFile(file).mkString
}
object ImplicitDemo{
implicit def file2RichFile(file:File) = new RichFile(file)
}
def main(args: Array[String]): Unit = {
import ImplicitDemo.file2RichFile
val file = new File("./data/1.txt")
val str = file.read()
println(str)
}
}
1.3.【结论】自动导入隐式转换方法
当隐式转换方法,与A对象调用B的.m()代码在同一作用域时,可省略 import隐式转换方法,就叫自动隐式转换
当对象调用类中不存在的方法或者成员时,编译器会自动去寻找并进行隐式转换
当方法中的参数类型与目标类型不一致时,编译器也会自动去寻找隐式转换
示例
object ImplicitFunc {
class RichFile(file:File){
def read() = Source.fromFile(file).mkString
}
def main(args: Array[String]): Unit = {
implicit def file2RichFile(file:File) = new RichFile(file) // 只要定义在一个object中就可以
val file = new File("./data/1.txt")
val str = file.read()
println(str)
}
}
# 隐式转换方法 增强List
object Test2 {
class RichList(list:List[Int]){
def avg() = {
if(list.length == 0) None else Some(list.sum / list.length)
}
}
def main(args: Array[String]): Unit = {
implicit def list2RichList(list:List[Int]) = new RichList(list)
val a = List(1,2,3,4,5)
val b = a.avg()
println(b) // 效果:3
}
}
2.隐式参数
2.1.【结论】作用
一个方法原来只有一个参数列表,有n个参数,现在想不修改它的第一个参数列表,以防影响之前别人对它的调用,但是要给此方法增加m个参数,然后在方法内部修改方法体,来使用m个新参数
就要将m个参数作为方法的第二个参数列表,声明为隐式参数列表,在原来别人调用它的代码之前,先使用隐式参数默认值来对第二个参数列表中的参数依次设置默认值,然后再调用,从而不影响原来别人对这个方法的调用
以后调用这个方法时,有可以根据需要选择给第二个参数列表是否传递参数,如不传参,就依然先使用隐式参数默认值来对第二个参数列表中的参数依次设置默认值,然后再调用
2.2.【结论】手动导入隐式参数的默认值
# 0.给方法增加一个隐式参数列表,并在方法体中使用隐式参数
def show(name:String)(implicit a:String, b:Int) = name + a + b
# 1.单例类中定义隐式参数的默认值,根据数据类型来与参数对应
object ImplicitDemo1{
implicit val x = "a"
implicit val y = 18
}
# 2.调用方法时,调用隐式参数默认值
def main(args: Array[String]): Unit = {
import ImplicitDemo1.x
import ImplicitDemo1.y
val d = show("name")
}
# 正常调用方法,不使用隐式方法默认值
val e = show("name")("aya", 2333)
示例
object ImplicitParam {
// 0.给方法增加一个隐式参数列表,并在方法体中使用隐式参数
def show(name:String)(implicit a:String, b:Int) = name + a + b
// 1.单例类中定义隐式参数的默认值,根据数据类型来与参数对应
object ImplicitDemo1{
implicit val x = "a"
implicit val y = 18
}
def main(args: Array[String]): Unit = {
// 2.调用方法时,调用隐式参数默认值
import ImplicitDemo1.x // 手动导入隐式参数默认值
import ImplicitDemo1.y // 手动导入隐式参数默认值
val d = show("name")
println(d) // 效果:namea18
// 正常调用方法,不使用隐式方法默认值
val e = show("name")("aya", 2333)
println(e) // 效果:nameaya2333
}
}
2.3.【结论】自动导入隐式参数的默认值
当隐式参数的默认值,与调用方法的代码在同一作用域时,可省略 import隐式方法默认值,就叫自动导入隐式参数的默认值
示例
object ImplicitParam {
// 0.给方法增加一个隐式参数列表,并在方法体中使用隐式参数
def show(name:String)(implicit a:String, b:Int) = name + a + b
// 1.单例类中定义隐式参数的默认值,根据数据类型来与参数对应
def main(args: Array[String]): Unit = {
// 定义隐式参数的默认值
implicit val x = "a"
implicit val y = 18
// 2.调用方法时,自动调用隐式参数默认值
val d = show("name")
println(d) // 效果:namea18
// 正常调用方法,不使用隐式方法默认值
val e = show("name")("aya", 2333)
println(e) // 效果:nameaya2333
}
}