• 详解 Scala 的隐式转换


    编译器第一次编译失败的时候,会在当前的环境中查找能让代码编译通过的方法,用于将某个类型进行转换,实现二次编译通过

    一、隐式函数

    隐式函数可以在不修改任何代码的情况下,扩展某个类的功能

    /**
    	声明语法:
    	implicit def funcName(param: Type1): Type2 = {}
    */
    // 使用隐式函数扩展 Int 类型功能
    object TestImplicitFunc {
        def main(args: Array[String]): Unit = {
            // 实现 12.myMax(15) 取最大值功能
            // val maxValue = 12.myMax(15) // Int 类型没有该方法
            
            // 1. 显式的将 Int 转换为 MyRichInt(通用性不强,每次调用都要手动转换)
            val myRichInt = new MyRichInt(12)
            println(myRichInt.myMax(15)) 
            
            // 2. 定义隐式函数转换(必须在方法调用之前定义)
            // 12.myMax(15) // 编译error
            implicit def convert(num: Int): MyRichInt = new MyRichInt(num)
            
            println(12.myMax(15))
            
        }
    }
    
    // 定义一个类,并声明要扩展的方法
    class MyRichInt(val self: Int) {
        def myMax(num: Int): Int = if(num > self) num else self
        def myMin(num: Int): Int = if(num > self) self else num
    }
    

    二、隐式参数

    普通方法或者函数中的参数可以通过 implicit 关键字声明为隐式参数,调用该方法时,编译器会在相应的作用域寻找符合类型的隐式值传入方法

    /**
    	定义:
    		implicit val varName: Type = value
    		func(implicit param: Type,...)
    	特点:
    		1.同一个作用域中,相同类型的隐式参数值只能有一个
    		2.编译器按照隐式参数的类型去寻找对应类型的隐式值,与隐式值的名称无关
    		3.隐式参数优先于默认参数
    */
    object TestImplicitParam {
        def main(args: Array[String]): Unit = {
            implicit val str: String = "tom"
            // implicit val str2: String = "jack" // error
            implicit val num: Int = 18
            
            def sayHello()(implicit name: String): Unit = println("hello, " + name)
            def sayHi(implicit name: String = "jerry"): Unit = println("hi, " + name)
            sayHello
            sayHello()
            sayHi // tom,隐式参数优先于默认参数
            // sayHi() // error
            
            // 方法定义省略隐式参数声明,使用 implicitly[] 方法指定要的隐式参数值类型
            def printAge(): Unit = println("Age: " + implicitly[Int])
            printAge()
        }
    }
    

    三、隐式类

    在 Scala2.10 后提供了隐式类,可以使用 implicit 声明类,可以扩展类的功能,相当于加强版隐式函数

    /**
    	定义语法:
    		implicit class className(param: Type) {}
    	要求:
    		1.其所带的构造参数有且只能有一个
    		2.隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是顶级的
    */
    // 使用隐式类扩展 Int 类型功能
    object TestImplicitClass {
        // 定义一个隐式类,并声明要扩展的方法(必须被定义在“类”或“伴生对象”或“包对象”里)
        implicit class MyRichInt(val self: Int) {
            def myMax(num: Int): Int = if(num > self) num else self
            def myMin(num: Int): Int = if(num > self) self else num
        }
        // 隐式类在方法调用之前定义
        
        def main(args: Array[String]): Unit = {
            println(12.myMax(15)) 
            println(12.myMin(15))
        }
        
    }
    

    四、隐式解析机制

    • 首先会在当前代码作用域下查找隐式实体(隐式方法、隐式类、隐式对象)
    • 如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。类型的作用域是指与该类型相关联的全部伴生对象以及该类型所在包的包对象
  • 相关阅读:
    GitHub上标星120k的Java进阶面试教程等!(建议收藏)
    Sora来袭!机器人+Sora落地性如何?
    Matlab论文插图绘制模板第46期—帕累托图(Pareto)
    【马蹄集】—— 数论专题
    使用 Wireshark 抓包工具快速分析 IoT 物联网终端设备的网络通信行为
    Typescript语言基础
    Prometheus+Grafana监控
    Jmeter常用参数化技巧总结!
    使用vs查看虚函数内存分布
    释放资源 try-catch
  • 原文地址:https://blog.csdn.net/weixin_44480009/article/details/139274714