1、隐式转换介绍
object Scala01_implicit {
def main(args: Array[String]): Unit = {
//隐式转换(自动转换)
//scala默认情况下支持数值类型的自动转换
//Byte->Short->Int->Long
//scala默认情况下支持多态的自动类型转换
//child->parent->trait(interface)
//scala也支持自定义隐式转换
//将两个无关的类型通过编程手段让他们可以自动转换
implicit def transform(d:Double): Int ={
d.toInt
}
val i : Int = 5.0
println(i)//5
}
}
- 隐式转换(自动转换)
- scala默认情况下支持数值类型的自动转换
Byte->Short->Int->Long- scala默认情况下支持多态的自动类型转换
*child->parent->trait(interface)- scala也支持自定义隐式转换
将两个无关的类型通过编程手段让他们可以自动转换
2、隐式转换增强功能(在不改变原有代码的基础上,增强功能)
object Scala01_implicit {
def main(args: Array[String]): Unit = {
implicit def transform(myslq:Mysql): Operater ={
new Operater()
}
val mysql: Mysql = new Mysql()
mysql.insert()
mysql.delete() //因为隐式转换,mysql已经是Operater类型,所以可以调用delete方法
}
}
class Operater{
def delete(): Unit ={
println("删除方法 ...")
}
}
class Mysql{
def insert(): Unit ={
println("插入方法 ...")
}
}
3、隐式值与隐式参数
object Scala03_implicit {
def main(args: Array[String]): Unit = {
def test(name : String): Unit ={
println("hello "+name)
}
def test1(name : String = "lisi"): Unit ={
println("hello "+name)
}
implicit val username : String = "wangwu"
def test2(implicit name : String = "lisi"): Unit ={
println("hello "+name)
}
test("zhangsan") // hello zhangsan
test1() //hello lisi 入参指定了默认值时,可以不写入参,但一定要写()
test2 // hello wangwu 使用隐式转换,不要带小括号
test2() // hello lisi 方法调用时使用小括号,会导致隐式转换无法传递
}
}
总结:如果隐式参数存在默认值、对应参数的隐式值,那么优先采用隐士值,如果找不到,采用默认值,再找不到,报错
4、隐式类
object Scala05_implicit {
def main(args: Array[String]): Unit = {
val user5:User5 = new User5()
user5.insert() // insert ...
user5.detele() // detele ...
}
// 1、隐式类相当于包装类
// 2、有且只有一个参数:需要报包装的对象(值)
implicit class Person5(u:User5){
def detele(): Unit ={
println("detele ...")
}
}
class User5(){
def insert(): Unit ={
println("insert ...")
}
}
}
隐式类使用有如下几个特点:
1)其所带的构造参数有且只能有一个
2)隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是 顶级的(top-level objects)。
3)隐式类不能是case class(case class在后续介绍 样例类)
4)作用域内不能有与之相同名称的标识符
5、隐式转换的解析机制(隐式转换的搜索范围)
即编译器是如何查找到缺失信息的,解析具有以下两种规则:
- 首先会在当前代码作用域下查找隐式实体(隐式方法、隐式类、隐式对象)。
- 如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。类型的作用域是指与该类型相关联的全部伴生模块,一个隐式实体的类型T它的查找范围如下(第二种情况范围广且复杂在使用时,应当尽量避免出现):
a) 如果T被定义为T with A with B with C,那么A,B,C都是T的部分,在T的隐式解析过程中,它们的伴生对象都会被搜索。
b) 如果T是参数化类型,那么类型参数和与类型参数相关联的部分都算作T的部分,比如List[String]的隐式搜索会搜索List的伴生对象和String的伴生对象。
c) 如果T是一个单例类型p.T,即T是属于某个p对象内,那么这个p对象也会被搜索。
d) 如果T是个类型注入S#T,那么S和T都会被搜索。
//解释b项
object Scala06_implicit {
def main(args: Array[String]): Unit = {
val user6:Users6 = new Users6()
user6.insert() // insert ...
user6.detele() // detele ...
}
class Users6() extends Test6 {
def insert(): Unit ={
println("insert ...")
}
}
}
trait Test6{
}
object Test6{
implicit class Person6(u:Users6){
def detele(): Unit ={
println("detele ...")
}
}
}