scala隐式转换

隐式转换--基本

// 关键字:implicit
// 隐式函数必须要在作用域范围内定义
// 隐式转换函数的 函数名自定义
// 隐式函数可以有多个,但是不能有重复的(函数名不能有重复,参数不能有重复)
// 代码中有下划线的地方表示使用了隐式转换
implicit def f1(d: Double): Int { d.toInt}  // 将double类型数据转换为int型
implicit def f2(d: Float): Int { d.toInt}

// 将Double或Float数据赋值给 int 型,调用了隐式转换
val num: Int = 3.5 // 底层编译 f1$1(3.5)

/////////////////////////////////////////////////////////////////////////////
// 可以通过隐式行数丰富类库的功能,比如
// 定义一个ms对象,只有insert方法
class MS{
    def insert(): Unit = {
        println("insert")
    }
}

// 再定义一个db对象,有delete方法
class DB {
    def delete(): Unit = {
        println("delete")
    }
}

// 定义隐式函数,返回 DB对象
implicit def addDelete(ms: MS): DB = {
    new DB
}

val ms = new MS
ms.insert()  // ms对象的方法
ms.delete()  // 隐式函数中的db的方法

隐式转换--进阶

隐式参数优先级
1、传入值 > 隐式值 > 默认值
2、在隐式匹配时候,不能同时匹配多个
3、如果3个一个都没有,就会报错

// 定义字符串隐式值为 jack~
implicit val str1: String = "jack~"
// 参数使用了隐式变量,其值为上面定义的隐式变量
def hello(implicit name: String): Unit = {
    println("hello " + name)
}
// 不用传入参数,即可输出数据:hello jack~
hello

////////////////////////////////////////////

implicit val str1: String = "jack~"
// 参数中的 隐式变量使用了默认值,其优先级低于隐式值
def hello(implicit name: String = "scala"): Unit = {
    println("hello " + name)
}
// 不用传入参数,输出数据:hello jack~
hello


////////////////////////////////////////////

implicit val name: Int = 10
// 参数中匹配不到隐式值,会使用默认值
def hello(implicit name: String = "scala"): Unit = {
    println("hello " + name)
}
// 不用传入参数,输出数据:hello jack~
hello


////////////////////////////////////////////

implicit val str1: String = "jack~"
def hello(implicit name: String): Unit = {
    println("hello " + name)
}
// 传入值,优先级大于隐式值,输出数据:hello scala
hello("scala")

隐式转换--高阶

隐式类

// 隐式类必须在类、包对象、或伴生对象里面,不能单独在外面(顶级),因为其作用域不能确定
// 隐式类不能用于 样例类


class Ms{
    def sayOk():Unit = {
        println("sayOk")
    }
}


def main() = {
    implicit class db(val m: Ms) {
        def addSuffix(): String = {
            m + " scala"
        }
    }
    
    val ms new Ms  //创建一个Ms实例
    ms.sayOk()  // 调用自己的方法
    ms.addSuffix()  // 这个是隐式类的方法,因为传入了Ms后,创建了实例包含了此方法
}

其他

隐式转换的时机

1、当方法中的参数类型与目标类型不一致时
2、当对象调用所在类中不存在的方法或成员时,编译器会自动将对象进行隐式转换(根据类型)

隐式转换的陷阱

1、不能存在二义性,即多个隐式
2、不能嵌套使用:即隐式函数A如果是将小数转换为int,在隐式函数A中,不能使用 int=小数的情况。

原文地址:https://www.cnblogs.com/jaysonteng/p/14198064.html