一.隐式参数和隐式值

隐式参数是级别在中间的一种参数形式。在调用是可以写也可以不写。在有隐式参数的方法中,调用此方法,那么JVM虚拟机首先寻找的是传参,再传参没有找到的情况下,才会去寻找隐式参数,如果不巧的是隐式参数也没有,这是JVM还会去寻找参数默认值,如果都没有,则调用时会报错,提示需要传参,要么就去写隐式参数。

  • 用法如下:
package Implicit

object ImplicitDemo_value_parameter {
  def main(args: Array[String]): Unit = {
    //声明隐式值,注意同种类型只能声明一个值,否则运行错误(ambiguous--模糊的无法确定到底引用哪个值)
    implicit val x = 1
    implicit val y = "hello implicit"
    //隐式参数必须使用函数柯里化,且在函数参数列表最后一项,只可有一个implicit关键字修饰
    //隐式参数可有默认值,其优先级为:传指定参数>隐式值>默认值
    def showMsg(a:Int,b:Int)(implicit x1:Int=2,y1:String="hello"):Int={println(y1);a+b+x1}
    //调用时不传参数,优先使用隐式值
    println(showMsg(1, 2))//hello implicit 换行 4
    //调用时传入参数,优先级最大
    println(showMsg(1, 2)(7,"Hello Implicit"))//Hello Implicit 换行 10
  }
}

二.隐式函数

又称隐式转换,用于类型不匹配时自动转换类型或关联两个类(即类型增强)。
和隐式参数差不多,只不多这里将隐式参数换成了隐式函数。隐式函数可以在自己创建了某个类对象就拥有相应的方法。隐式参数就是不需要new相应的类的对象,就可以拥有它的方法。

package Implicit
class Person {
  def showMsg={println("我是一个人")}
}
class ImplicitDemo_function
object ImplicitDemo_function {
  def main(args: Array[String]): Unit = {
    //val s:Int =1.5 这种声明如果不写隐式转换函数,会直接报错,如果定义了隐式转换函数就可以自动转换为Int
    //定义转换函数需要根据需求来写,比如上面的例子需要把Double类型转化为Int类型
    implicit def double2int(x:Double):Int=x.toInt
    val  s:Int = 1.5
    //隐式转换函数也可使得两个毫无关系的类之间关联起来,也叫类型增强如下:
    implicit def demoToPerson(x:ImplicitDemo_function):Person=new Person
    val  demo = new ImplicitDemo_function
    //因为使用了隐式函数关联,可直接使用Person类的方法,这样两个毫无关系的类就可关联起来了,可随心所欲的扩展
    demo.showMsg//我是一个人
  }
}

三.隐式类

隐式类一般为实体类服务,可以隐式的为实体类增加方法。在实体类创建对象后自动获得此方法。相当于隐式类为目标类放开了权限,只要目标类创建了对象,该对象就可以调用隐式类中的方法。隐式类必须写在object类中,因为object类相当于java中的静态类,在代码执行前编译,这样才能被找到。一般来说隐式类写在一个包中最好,方便查找,包括隐式函数和隐式参数。

注意:隐式类只能声明在object中
举个例子详细说明隐式类的方法:使用jdbc连接mysql

1.定义隐式类

package MysqlUtil

import java.sql.{Connection, DriverManager, PreparedStatement, ResultSet}
import mysqldemo.MysqlPractice

object MySQLUtils {
  //声明隐式类必须在object中且构造方法需要有一个类作为参数,当new该类对象的时候只要导了该隐式类,就可使用隐式类的所有方法
  implicit class MySQLOP(obj: MysqlPractice) { //定义连接jdbc的隐式类
    //定义相关变量
    private val driver = "com.mysql.jdbc.Driver"
    //驱动
    private var connection: Connection = _
    //连接
    private var pstm: PreparedStatement = _
    //会话管理器
    private var rs: ResultSet = _
    //结果集
    //获取链接
    def conn(): Connection = {
      //加载驱动
      Class.forName(driver)
      //获取连接
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "sunyong")
      connection
    }
    //查询结果集
    def query(sql: String, param: Object*): ResultSet = {
      //获取连接
      conn()
      //使用连接获取会话管理器
      pstm = connection.prepareStatement(sql)
      //设置sql语句参数
      for (i <- 0 until param.length) pstm.setObject(i + 1, param(i))
      //执行查询
      rs = pstm.executeQuery()
      rs
    }
    //增删改
    def update(sql: String, params: Object*): Int = {
      //获取连接
      conn()
      //创建sql会话管理器
      pstm = connection.prepareStatement(sql)
      //设置sql语句参数
      for (i <- 0 until params.length) pstm.setObject(i + 1, params(i))
      //执行语句
      pstm.executeUpdate()
    }
    //关闭资源
    def close() = {
      if (rs != null) rs = null
      if (pstm != null) pstm = null
      if (connection != null) connection = null
    }
  }
}

2.创建隐式类的参数类型对象,调用隐式类方法

package mysqldemo

class MysqlPractice {
}
object MysqlPractice{
  def main(args: Array[String]): Unit = {
    //导包需要导到哪?-->必须导到隐式类所在的object对象中(或者进一步细化到该隐式类)
    // -->因为隐式类不允许写在顶级类上
    import MysqlUtil.MySQLUtils._ //或import MysqlUtil.MySQLUtils.MySQLOP
    //创建隐式类参数类型的对象
    val practice = new MysqlPractice
    //执行隐式类的方法
   val rs = practice.query("select * from student")
    while(rs.next()){
     // var name:String=rs.getString("name");
      var sex:String=rs.getString("sex");
      var age:String=rs.getString("age");
      println(sex+" "+age)
    }
    practice.close()
  }
}

课堂练习:

隐式参数:

class Son extends Person {
  def fun(a:Int,b:Int)(implicit c:Int,msg:String="hello"):Int= {
    println(msg)
    a+b+c
  }
}

object Demo{
  
  implicit val a:Int=10
  implicit val str:String="welcome"
  
  def main(args: Array[String]): Unit = {
    
    val son =new Son
    var sum=son.fun(7,8)
    println(sum)  //  welcome  25
    sum=son.fun(7,8)(11,"nihao")
    println(sum)  //  nihao  26
    
  }
}

等同于:

package nj.zb.kb09.implicitdemo

object Impliciteg {
  implicit val num:Int=10   //定义隐式参数
  implicit val msg:String="hello"
}
package nj.zb.kb09.implicitdemo

object Demo1 {
  def main(args: Array[String]): Unit = {
    import nj.zb.kb09.implicitdemo.Impliciteg._
    val result=sum(10,10)
    println(result)     //30
    showMsg("gree")     //hello:gree
  }

  def sum(a:Int,b:Int)(implicit c:Int):Int= {
    a+b+c
  }

  def showMsg(name:String)(implicit hi:String):Unit={
    println(hi+":"+name)
  }

}

隐式方法:

object Demo1 {
  
  implicit def doubleToInt(value:Double):Int=value.toInt
  implicit def stringToInt(value:String):Int=Integer.parseInt(value)

  def main(args: Array[String]): Unit = {

    val num:Int=3.5
    println(num)
    val num2:String="1"
    println(num2)

  }
}

等同于:

package nj.zb.kb09.implicitdemo

object Impliciteg {
  implicit def doubleToInt(value:Double):Int=value.toInt
  implicit def stringToInt(value:String):Int=Integer.parseInt(value)
}
object Demo1 {


  def main(args: Array[String]): Unit = {
    
    import nj.zb.kb09.implicitdemo.Impliciteg._
    
    val num:Int=3.5
    println(num)
    val num2:String="1"
    println(num2)

  }
}

隐式类:

package nj.zb.kb09.implicitdemo

object Impliciteg2 {

  implicit class NumOpertion(deom:Demo1){
    def ji(a:Int,b:Int):Int= a*b
    def shang(a:Int,b:Int):Int=a/b
    def add(a:Int,b:Int):Int=a+b
  }

}
package nj.zb.kb09.implicitdemo

class Demo1{}

object Demo1 {
  def main(args: Array[String]): Unit = {

    import nj.zb.kb09.implicitdemo.Impliciteg2._
    val dm=new Demo1
    println(dm.ji(12, 13))   //156
    println(dm.shang(12,2))  //6
    println(dm.add(11,24))   //35

  }
}

demo2:

package nj.zb.kb09.implicitdemo

object Impliciteg2 {

  implicit class Demo2Implicit(deom2:Demo2){
    def aa(s:String):Unit = println(s)
    def bb(num:Int):String={
      if(num%2==0) "偶数" else "奇数"
    }
    def add(num1:Int,num2:Int):Int= num1+num2
  }

  implicit class Demo2Implicit2(demo2:Demo2){
    def login(name:String,pwd:String):Boolean={
      if(name.equals("zs")&& pwd.equals("123")) true else false
    }
  }

}
package nj.zb.kb09.implicitdemo

class Demo2 {}

object Demo2{
  def main(args: Array[String]): Unit = {

    import nj.zb.kb09.implicitdemo.Impliciteg2._
    val demo2=new Demo2
    demo2.aa("abc")      //abc
    println(demo2.add(12, 12))  //24
    println(demo2.bb(3))    //奇数
    println(demo2.login("aa", "123"))   //false

  }
}