隐式转换:编译器 偷偷地,自动地帮我们把一种数据类型转换为另一种类型。
例如:Int --> Double
它有失败的时候(Double --> Int),有成功的时候
当它转换失败的时候,我们提供一个工具,让它能成功
object test {//明确地,把Double转成Intimplicit def X(d:Double):Int = {println("implicit X 被调用了")d.toInt}def main(args: Array[String]): Unit = {var i:Int = 1i = 2.1 //把Double 转入 Int.正常会报错
// j = i // 把Int 转入 Doubleprintln(i)}
}
内部流程如下图所示:
需求:
完成一个功能,让所有的字符串都能调用isPhone方法,来校验自己是不是一个手机号
object test1 {//开始你的代码class StrongString(val str:String){def isPhone(): Boolean = {val reg = "1[3-9]\\d{9}".rreg.matches(str)}}//定义一个特殊的转换函数,把str ==> StrongString的对象def tranform(str:String):StrongString = {new StrongString(str)}implicit def stringToStrongString(str: String): StrongString = {new StrongString(str)}def main(args: Array[String]): Unit = {val str = "13612345678"
// println(isPhone(str))
// println(isPhone("abc"))
// println((new StrongString(str)).isPhone())println( tranform("abc").isPhone() )println(str.isPhone()) // ==> trueprintln("136a".isPhone()) // ==> false}
}
2.函数的隐式参数
一直在修改原来的代码!!!
困难:函数有一个默认数值,在不传入具体的实参时,就会自动使用这个默认值。
难点在于,这个默认值不能修改!
object test {//函数参数的默认值def sayName(implicit name:String = "小明"): Unit = {println("我的名字是:" + name)}//隐式值implicit val value:String = "小张"def main(args: Array[String]): Unit = {sayName("小王")sayName()sayName}
}
结果如下:
3.隐式类
任务:给之前是BaseUser添加新的功能,但是,不要直接去改代码
思路:把BaseUser 通过隐式转换,改成一个新类型,而是这个新类型中有这新的方法
implicit class === 一个隐式转换函数 + 类
它的作用:拓展已有类的功能,而不需要去修改之前的类的代码
object test2 {implicit class PowerUser(b:BaseUser) {def updateUser() {println("updateUser")}}// def xxxxxx(b:BaseUser) : PowerUser = {
// new PowerUser()
// }// 10 年,小王写的代码class BaseUser{def showUser(): Unit = {println("showUser")}}def main(args: Array[String]): Unit = {val u1 = new BaseUser()u1.showUser()// transform(u1).updateUser() //希望要增加新的功能u1.updateUser() //希望要增加新的功能}
}
结果如下:
任务:给整数添加一个功能,求阶乘
相关代码如下:
import scala.language.postfixOps
// 需求:给整数添加一个功能,求阶乘
// 5! = 1*2*3*4*5 = 120
object test3 {implicit class xxxxx(d:Int) {def ! :Int = {println("阶乘函数被调用", d)// 写代码,完成1*2*3*...*dvar rs = 1for (i <- 1 to d ){rs *= i}rs}}def main(args: Array[String]): Unit = {println(5.!)println(6!)}
}
结果如下:
作用域:1.代码写在包对象
2.代码写在一个单独文件,要用的时候就导入
代码写在包对象时的情况如下:
//包对象中
package object test39 {implicit class xxxxx(d: Int) {def ! : Int = {println("阶乘函数被调用", d)// 写代码,完成1*2*3*...*dvar rs = 1for (i <- 1 to d) {rs *= i}rs}}
}
在同一个包(package test39)中可直接调用
package test39
object test4 {def main(args: Array[String]): Unit = {println(5.!)}
}
代码写在一个单独文件,要用的时候就导入时的情况如下:
//在单独文件中写
object pub {implicit class xxxxx(d: Int) {def ! : Int = {println("阶乘函数被调用", d)// 写代码,完成1*2*3*...*dvar rs = 1for (i <- 1 to d) {rs *= i}rs}}
}
使用时要调用该文件:
import pub._ //调用该文件
class test_39 {def main(args: Array[String]): Unit = {println(5.!)}
}
4.隐式对象
4.1隐式对象的定义
隐式对象是一个带有implicit关键字的单例对象,它可以用于提供某种类型的实例以供隐式转换使用。隐式对象通常用于将某个类或trait的实例隐式地注入到方法中。
//隐式对象
//implicit object
//作用:给函数的隐式参数提供默认值
object test5 {case class DatabaseConfig(driver: String, url:String)implicit object MySqlDefault extends DatabaseConfig("mysql","localhost:443")def getConn(implicit config: DatabaseConfig): Unit = {println(config)}def main(args: Array[String]): Unit = {
// getConn.DatabaseConfig("sqlite","localhost:80")getConn}
}
隐式对象和前面讲的隐式参数比较类似,都是用来设置初始数据的。