隐式转换:编译器 偷偷地,自动地帮我们把一种数据类型转换为另一种类型。
例如:Int --> Double
它有失败的时候(Double --> Int),有成功的时候
当它转换失败的时候,我们提供一个工具,让它能成功
object test {
//明确地,把Double转成Int
implicit def X(d:Double):Int = {
println("implicit X 被调用了")
d.toInt
}
def main(args: Array[String]): Unit = {
var i:Int = 1
i = 2.1 //把Double 转入 Int.正常会报错
// j = i // 把Int 转入 Double
println(i)
}
}
内部流程如下图所示:
需求:
完成一个功能,让所有的字符串都能调用isPhone方法,来校验自己是不是一个手机号
object test1 {
//开始你的代码
class StrongString(val str:String){
def isPhone(): Boolean = {
val reg = "1[3-9]\\d{9}".r
reg.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()) // ==> true
println("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*...*d
var rs = 1
for (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*...*d
var rs = 1
for (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*...*d
var rs = 1
for (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
}
}
隐式对象和前面讲的隐式参数比较类似,都是用来设置初始数据的。