9、scala基础语法-隐式转换

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 ...")
    }
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容