20.3 隐式参数

2016-05-08 14:16:56 3,124 0

所谓隐式参数指的是,我们的函数或者方法中的参数可以有隐式值,或者说是默认值。通过提供隐式参数,我们在调用函数的时候,可以不提供参数,scala会自动去查找隐式值,当然隐式值也是需要我们提供的。

在Scala中,如果我们的方法定义的参数列表以implicit开头,则方法参数列表中的参数都是隐式参数。在提供了隐式值的情况下,我们调用方法时,不需要提供参数。

1、入门案例

object ImplicitDemo {
  //隐式值
  implicit val xx: String = "tianshouzhi"
  implicit val yy: Int = 25
  
  //隐式参数
  def test(implicit name: String, age: Int) {
    println("name:" + name + ",age:" + age)
  }
  
  def main(args: Array[String]): Unit = {
    test//注意没有携带参数
  }
}

运行程序的结果为:

name:tianshouzhi,age:25

可以看到了,方法的参数列表加了implicit之后,会自动查找隐式值,隐式值同样以implicit开头

2、Scala是如何为隐式参数提供隐式值的?

Scala是通过类型检查来为隐式参数提供默认值。因为在test方法中的参数,一个是String类型,一个是Int类型,而我们提供的2个隐式值分别为

implicit val xx: String = "tianshouzhi" //String类型
implicit val yy: Int = 25 //Int类型

因为提供的隐式值类型刚好能匹配上,因此调用的时候可以不传递参数。

此外,需要注意的是, 因为是按照类型进行匹配的。所以隐式参数列表中相同类型的参数,都会被赋予同样的值。例如,我们修改test方法

 //增加address参数
  def test(implicit name: String, age: Int,address:String) {
    println("name:" + name + ",age:" + age+",address:"+address)
  }

修改后的方法有2个String类型的参数,而隐式值是按照参数类型进行匹配的,因此这两个String类型的参数的隐式值都是"tianshouzhi"。

读者可以运行程序进行测试

name:tianshouzhi,age:25,address:tianshouzhi

如果隐式参数列表中,只要有一个参数没有默认值,那么我们在调用的时候,就必须要传递所有的参数。假设,一个方法接受五个不同的类型的隐式参数,即使我们提供了4种类型的隐式值,因为还有一种类型没有隐式值,我们在调用函数的时候也需要提供所有的参数。

那么如果我们只能提供参数列表中部分的隐式值。但是又只想提供没有隐式值的那个类型的参数,改怎么办?此时应该使用柯里化函数。如

object ImplicitDemo {
  //隐式值
//  implicit val xx: String = "tianshouzhi"
  implicit val yy: Int = 25
  
  //隐式参数
  def test( name: String)(implicit age:Int){
		  println("name:" + name + ",age:" + age)
  }
    
  def main(args: Array[String]): Unit = {
    test("tianshouzhi")
  }
}

需要注意的是,柯里化后的函数,必须要将不能提供隐式值的参数,放到方法的参数声明的最前面。以下的这种声明方式是错误的

//隐式参数
  def test(implicit age:Int)( name: String){
		  println("name:" + name + ",age:" + age)
  }

因为违反了规定,name没有隐式值,确放到了方法参数的列表的最后面。