d通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码。
- 使得静态类型动态化
- 为现有类库添加功能
- 隐式的代理增强一个类或者一个方法
1. 隐式变量
使用 implicit修饰的变量称之为隐式变量 ,同一种类型的隐式变量在上下文中只能声明一个
object MyValue {
implicit val age:Int = 19
implicit val name:String = "lisi"
}
/**
* 这个方法的所有的参数是隐式参数
* 可以使用柯里化来定义个别的隐式参数
* add(x:Int)(implicit y:Int , z:Int)
* 上面的例子中x为正常参数 y z都为隐式参数
* @param name
* @param age
*/
def myShow(implicit name: String, age: Int): Unit = {
println(name + " " + age)
}
调用函数的时候可以不用写隐式类型的参数 , 会从上下文环境中获取
def main(args: Array[String]): Unit = {
new Show().myShow("reba",12)
// 导入了隐式参数 就会从context中寻找隐式数据
// context中只能有一个匹配类型的数据
// 如果找到多个匹配类型的数据就会报错
import MyValue._
//lisi 19
new Show().myShow
}
隐式值可以为方法提供隐式参数
2 隐式函数
函数处理的数据类型 => 返回的数据类型 , 当遇到对应的类型=>类型处理的时候隐式函数会自动的应用
增强一个类
添加不存在的函数,implicit作用于函数,称之为隐式函数
class A[T] {
def mymax1(x:T ,y:T): T ={
if(x > y) x else y// T类型中没有定义>方法 报错
}
// T类型必须是可以隐式的转换成Ordered的类型 , 这个隐式转换要事先定义
def mymax2(x:T ,y:T)(implicit order:T=>Ordered[T]): T ={
if(x > y) x else y
}
}
object A{
def main(args: Array[String]): Unit = {
// Int已经默认的实现了 Orderd的实时转换
val res: Int = new A[Int]().mymax2(12,34)
println(res)
}
}
/**
* 定义一个隐式方法
* 处理两个String类型返回一个String类型
* @param str
* @param str2
* @return
*/
implicit def m(str:String, str2:String)={
str.toUpperCase+"--"+str2.toUpperCase
}
/**
* 定义一个方法 方法的第二个参数列表是一个隐式的函数为参数
* @param str
* @param f
* @return
*/
def m2(str:String)(implicit f:((String,String)=>String)): String ={
f(str,str)
}
def main(args: Array[String]): Unit = {
// 当调用方法的的时候 , 从上下文中找隐式函数, 直接饮用
println(m2("tom")) //TOM--TOM
}
3 隐式类(隐式视图)
把一种类型自动转换成另外一种类型,进而使用另外一种类型中的属性和方法,从而满足表达式的要求.
隐式类约束
隐式类必须有一个带一个参数的主构造函数
必须定义在另一个class/object/trait里面(不能独立定义)
隐式类构造器只能带一个不是implicit修饰的参数
作用域中不能有与隐式类类型相同的成员变量,函数以及object名称
定义一个普通的类 只有一个add方法
class B {
val add = (x: Int, y: Int) => {
x + y
}
}
定义一个隐式类
**
* 隐式主题类
*/
object ImplicitContext{
//隐式类只能对一种类型的类进行增强 B类或者子类增强
implicit class RichB(b:B){
def multiply(x: Int, y: Int) = {
x * y
}
}
}
效果 B类中具有了隐式类中的multiply()方法
def main(args: Array[String]): Unit = {
val b = new B // B类 以及他的子类
println(b.add(12, 12))
import ImplicitContext._
println(b.multiply(12, 12))
}
如果代码无需隐式转换即可通过编译,则不会引入隐式转换
隐式转换只会匹配一次,即隐式转换至多发生一次
存在二义性的隐式转换报错,
列子增强File类 , 具有读取行数据的能力
/**
* @Auther: 多易教育-行哥
* @Date: 2020/6/27
* @Description:
*/
object TestIm {
implicit class RichFile(file: File) {
def getLines() = {
Source.fromFile(file).getLines()
}
}
def main(args: Array[String]): Unit = {
val file = new File("d://data/app.txt")
// 如果没有上面的隐式类, file中是没有getlines方法的
file.getLines().foreach(println)
}
}