56_隐式转换
/*
* 1. 什么是隐式转换?
* 1. 当编译器第一次编译代码失败时
* 会自动在当前环境中查找能使代码通过编译的方法(通常是数据类型转换)
* 也可以称之为 二次编译
*
* 2. 隐式转换发生在什么时候?
* 1. 发生在编译时期,编译器会自动帮助我们做一些事情
*
* 3. 隐式转换的修饰的位置
* 1. 隐式函数
* 语法 : implicit def f1(参数列表) ...
*
* 2. 隐式类
* 语法 : implicit class objName ...
*
* 要求 : 1. 所带的构造参数 有且只能有一个
* 2. 隐式类必须定义在 类或伴生对象或包对象中
* 即隐式类不能作为 顶级对象
* implicit' modifier cannot be used for top-level objects
*
* 3. 隐式参数
* 语法 : implicit val id:Int = 10 -- 隐式变量
* def f1(implicit str:Int) -- 隐式参数
*
* 4. 隐式解析机制(Scala语法)
* 1. 首先会在当前代码作用域下查找隐式实体(隐式方法、隐式类、隐式对象) (一般是这种情况)
* 2. 如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。
* 类型的作用域是指 与该类型相关联的全部伴生对象以及该类型所在包的包对象
* */
-- 1.隐式函数
class MyInt(val self: Int) { println("MyInt 对象初始化了") def Max(i: Int): Int = if (self >= i) self else i def Min(i: Int): Int = if (self >= i) i else self } object ImplicitFunction extends App { // 1.需求 : Int类型的对象,定义比较大小的方法,并返回最大值 // 13.Max(20) 返回 20 // 2.思路 : 定义 Int类型的包装类 MyInt,定义Max方法 // 通过调用 MyInt 来完成需求 println(s"获取max:${new MyInt(13).Max(20)}") println(s"获取max:${new MyInt(21).Max(20)}") // 3. 思考 : 每次 完成13.Max(20) 都需要创建 MyInt对象,有没有更简洁的办法呢? // 可以定义一个 隐式的转换函数,在每次编译的时候,自动将Int对象 转换成MyInt对象 implicit def Int2MyInt(i: Int): MyInt = { println("隐式函数-Int2MyInt-调用了") new MyInt(i) } println(s"获取max:${13.Max(20)}")
// 隐式调用 会将13作为参数 去当前作用域下去寻找是否有一个函数 参数类型为Int 返回值类型为MyInt
// 如果找到了 将会自动调用 将13.Max(20) => 隐式函数(13).Max(20) // 4. 思考 // 1. 隐式函数的编译流程 是怎样的? // 1. 在编译代码时,如果发生编译类型错误,不会立即报错 // 而是根据 参数类型和返回值类型 去当前代码的作用域下 // 寻找有没有 将类型转换的函数,如果找到 则会自动调用 // 2. 注意事项 // 1. 同一作用域下 同一类型(参数类型 + 返回值类型 相同)的隐式函数只能有一个 }
-- 2.隐式类
object ImplicitClass extends App { //1. 思考 : 在上述需求中,通过隐式函数 完成了 13.Max(20) // 但是 一旦离开该作用域(比如其他对象或类中),则需要重新 定义隐式转换函数 // 有没有方便的方法,不用定义隐式转换函数,就能完成自动类型转换呢? //2. 思路 : 可以定义一个 隐式类,通过类的构造器,完成自动类型转换 implicit class MyInt(val self: Int) { println("MyInt 对象初始化了") def Max(i: Int): Int = if (self >= i) self else i def Min(i: Int): Int = if (self >= i) i else self } println(s"获取max:${13.Max(20)}") // 隐式调用 //3. 注意事项 // 1. 隐式类所带的构造器,有且只能有一个参数 // 2. 隐式类 必须被定义在 "类"或者"伴生对象"或者"包对象"里 // 也就是隐式类不能作为顶级类 // implicit' modifier cannot be used for top-level objects }
-- 3.隐式参数
object ImplicitPara extends App { //1. 思考 : 调用方法时,不指定参数时,也想有参数传递 //2. 思路 : // 1. 可以使用 默认参数(弊端 :只能在函数定义时,指定参数默认值) // 2. 可以使用 隐式参数(可以动态指定实参的值) //定义 隐式变量 implicit var str: String = "大王" implicit var str1: Int = 100 //隐式参数 def f1(implicit str: String): Unit = println(s"f1方法:${str}") def f2(implicit str: String = "小王"): Unit = println(s"f2方法:${str}") //方法体内调用 隐式变量 def f3 = println(s"f2方法:${implicitly[Int]}") //调用 f1 f1("new") f2 f2("new") f3 //3. 说明 // 1. 调用流程 // 通过参数类型 去匹配同作用域下的同类型 隐式变量 // 2. 注意事项 // 同作用域下 同类的隐式变量只能定义一个 // 当定义多个 同类型的隐式变量时, 将造成无法匹配 // 3. 隐式参数和 默认参数 的优先级 谁高呢? // 隐式参数 > 默认参数 }
//隐式解析机制(测试作用域)
/*
* 1. 首先在 当前作用域下查找 符合条件的 隐式变量
* 2. 当前作用域如果没找到
* 会继续在隐式参数的类型的作用域里查找
* 类型的作用域是指 : 与该类型相关联的全部伴生模块
* */
object ImplicitScope extends App with PersonTrait { //1. 首先会在当前代码作用域下查找隐式实体 val teacher = new Teacher() teacher.eat() teacher.say() //会继续在隐式参数的类型的作用域里查找 class Teacher { def eat(): Unit = println("eat...") } } trait PersonTrait { } object PersonTrait { // 隐式类 : 类型 1 => 类型 2 implicit class Person5(user: Teacher) { def say(): Unit = println("say...") } }
分类:
Scala
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通