• implicit关键字详解


    implicit

    1. implicit是scala中的一个关键字,下面从五个方面介绍下implicit
      1. 隐式转换函数:implicit def int2str(x:Int):String = x.toString
      2. 隐式类:implicit class Student(x: Int) {    }
      3. 隐式参数:def Student[T](x:T,y:T)(implicit ordered: Ordering[T]):Int = ordered.read(x,y)
      4. 隐式值:implicit val x: Int = 0
      5. 隐式对象:implicit object obj {}
    2. Scala支持两种形式的隐式:
      1. 隐式值:用于给方法提供参数(隐式转换函数,隐式对象都可以作为隐式值为方法提供隐式参数)
      2. 隐式视图:用于对象类型间的转换使函数的调用能够编译通过(隐式转换函数,隐式类都可以看成是隐式视图的隐式转换)
    3. 作用:通过隐式转换可以极大的减少代码量,让编译器去去搜索作用域内的implicit修饰信息进行隐式转换、隐式赋值
    4. implicit修饰的都必须满足无歧义规则
    5. 隐式转换的存放的地点:需要导入包 :import com.bigdata.study.scala._
      1. 当前程序可见作用域
      2. 原类型的伴生对象中
      3. 其他object中

    隐式转换函数

    1. 隐式转换函数:使用implicit关键字修饰的函数
    2. 隐式转换的前提:
      1. 隐式转换函数只接受一个参数,对于接受多参数的隐式函数来说就没有隐式转换的功能
        implicit def int2str(x:Int):String = x.toString // 正确
        implicit def int2str(x:Int,y:Int):String = x.toString // 错误
      2. 不支持嵌套的隐式转换
        class A{
             def hi = println("hi")
            }
        
            implicit def int2str(x:Int):String = x.toString 
        
            implicit def str2A(x:Int,y:Int):A = new A
        
            "str".hi  // 正确
            1.hi      // 错误
      3. 不能存在二义性,即同一个作用域不能定义两个相同类型的隐式转换函数(即是不能存在两个都是将类型a转换成类型b的函数)
        implicit def int2str(x:Int):String = x.toString 
        implicit def anotherInt2str(x:Int):A = x.toString
      4. 代码能够在不使用隐式转换的前提下能编译通过,就不会进行隐式转换(即当表达式在编译不通过的情况下才会调用隐式转换,如果编译通过就不调用)
    3. 一个对象调用一个函数编译不通过只有两个原因:a.fun(b) 
      1. 当方法中的参数的类型b与目标类型不一致时
      2. 当对象a调用类中不存在的方法或成员时
    4. 隐式转换的顺序:隐式转换使表达式通过编译的顺序是 b到a.(先对b进行转换看是否通过,如果不通过在对a进行转换,如果都转换之后还不通过就报错)
    5. 隐式转换的作用:
      1. 编译器会在当前作用域寻找合适的隐式转换使将a或者对象b进行转换类型使编译通过
      2. 就是扩展已有的类,在不修改原有类的基础上为其添加新的方法、成员(把一种类型自动转换成另外一种类型,进而使用另外一种类型中的属性和方法)

      例子:

    object ImplicitDemo {
        // TODO:定义隐式转换函数,地点一 -> 当前程序可见作用域
        implicit def man2SuperMan(man: Man): SuperMan = new SuperMan(man.name)
        def main(args: Array[String]): Unit = {
            // 平时的时候,普通人, 该上学的上学
            val man = new Man("super")
            // 怪兽出现,毁灭人类,普通人变身奥特曼,吊打怪兽
            import com.erongda.bigdata.scala.oop.demo07.AA._
            man.emitLaser()
        }
    }

    隐式类

    1. Scala2.10引入了一种叫做隐式类的新特性。隐式类指的是用implicit关键字修饰的类。在对应的作用域内,带有这个关键字的类的主构造函数可用于隐式转换。
    2. 限制条件:
      1. 只能在别的trait/类/对象内部定义。
        object Test {implicit class person(x: Int)} // 正确! 
        implicit class person(x: Double) // 错误!
      2. 构造函数只能携带一个非隐式参数(虽然我们可以创建带有多个非隐式参数的隐式类,但这些类无法用于隐式转换。)
         implicit class Test(str: String) // 正确!
         implicit class Test[T](str: String, index: Int) // 错误!
         implicit class Test[T](str: String)(implicit index: Index) // 正确!
      3. 在同一作用域内,不能有任何方法、成员或对象与隐式类同名。(注意:这意味着隐式类不能是case class。)
        object Test{
          def main(args: Array[String]): Unit = {
            implicit class Test(x: Int) // 错误!
            val x = 1
            implicit class x(y: Int) // 错误!
            implicit case class Baz(x: Int) // 错误!
          }
        }
    3. 隐式类和隐式转换函数区别:都是实现隐式转换,各有优点(比如:a想添加b方法)
      1. 隐式转换函数:首先创建一个有b方法的类c ,在写一个隐式转换函数fun(a)将对象a变成对象c
      2. 隐式类:构造一个隐式类c(a),将参数a的类型转换成自己的类型c,直接调用b方法 
      3. 优缺点:隐式类比隐式转换函数更加简单,但是隐式转换函数的功能更加强大,因为需要多个对象object1,object2,object3添加方法,隐式类需要为每一个对象创建一个隐式类(方法),隐式转换函数只需要创建一个对象(方法),为每个object1,object2,object3添加一个隐式转换函数即可

     

    object ImplicitTest {
      class  Man{}
      //隐式类
    implicit  class Teacher(man: Man){
      def fly: Unit = {
        println("在教书")
      }
    }
      //隐式转换函数
      class Student(man:Man){
        def study: Unit ={
          println("在学习")
        }
      }
    implicit def ManToStudent(man:Man)=new Student(man)
      def main(args: Array[String]): Unit = {
        val man = new Man
        man.fly
        man.study
      }
    }

    隐式参数

    1. 隐式参数:使用关键字implicit进行标识参数就是隐式参数,隐式参数一般和普通的参数放在两个不同的括号中(def student(name:String)(implicit age:Int))
    2. 函数的调用:在调用含有隐式参数的函数时可以不用传递隐式参数,编译器会自动寻找合适的隐式值当做隐式参数,而只有用implict标记过的值、对象、函数才能被找到。
    3. 隐式参数有默认值,可以用赋值,也可以当做一个普通的参数那样进行赋值

    寻找隐式值

    object ImplicitTest {
      def main(args: Array[String]): Unit = {
        implicit val ages = 12
        def student(name:String)(implicit age:Int): Unit ={
          println(s"$name 今年 $age 岁了")
        }
        student("Tom")
        student("Tom")(15)
      }
    }

    寻找隐式对象和隐式函数

    object ImplicitTest {
      def main(args: Array[String]): Unit = {
    //    例如自动寻找隐式对象:
        implicit object Student {
          def Study(s:String) = println(s"好好学习 $s!")
        }
        def test(s:String)(implicit stu: Student.type ) = {
          stu.Study(s)
        }
        test("Tom")   //
    //    自动寻找隐式函数:
        implicit def int2str(x: Int): String = x.toString
    
        def test1(x: Int, fun: String => Unit)
                 (implicit age: Int => String) = {
          fun(age(x))
        }
        test1(12, println) // 打印出"12"
      }
    }
  • 相关阅读:
    php No input file specified 错误提示
    yii 隐藏index.php
    phpstudy 配置 sqlserver
    xdebug3 配置信息
    composer 更新
    mysql 命令行 导入大型文件
    使用 DBExportDoc V1.0 For MySQL 导出数据库表结构说明文档
    聚合数据接口调用实例
    servlet
    JDBC
  • 原文地址:https://www.cnblogs.com/WeiKing/p/11613472.html
Copyright © 2020-2023  润新知