定义一个方法,其中包含一个隐式参数. 那么调用的时候可以不用把这个隐式参数传进去, 解释器会自己找一个用implicit定义的变量,不管这个变量名字叫啥,都会把这个变量传给方法中的隐式参数.
//定义一个方法,有一个隐式参数
scala> def person(implicit name : String) = name
person: (implicit name: String)String
//直接调用,出错,因为找不到隐式参数
scala> person
<console>:29: error: could not find implicit value for parameter name: String
person
^
//定义一个隐式变量
scala> implicit val p = "mobin"
p: String = mobin
//再次执行,ok
scala> person
res7: String = mobin
//在定义一个隐式变量
scala> implicit val p1 = "mobin1"
p1: String = mobin1
//再次调用,出错,隐式参数太多,不知道用哪个
scala> person
<console>:33: error: ambiguous implicit values:
both value p of type => String
and value p1 of type => String
match expected type String
person
^
//定义一个方法,含有一个隐式参数
scala> def person1(age:Int)(implicit name : String): String = name+age
person1: (age: Int)(implicit name: String)String
//找不到隐式参数
scala> person1(10)
<console>:26: error: could not find implicit value for parameter name: String
person1(10)
^
//隐式参数也可以显式传入
scala> person1(10)("libai")
res2: String = libai10
//定义一个隐式变量
scala> implicit val a="doubi"
a: String = doubi
scala> person1(10)
res4: String = doubi10
scala> implicit val b="liubei"
b: String = liubei
//同样作用域隐式变量不能定义多个
scala> person1(10)
<console>:30: error: ambiguous implicit values:
both value a of type => String
and value b of type => String
match expected type String
person1(10)
^
隐式变量也可以定义在其他object
使用时导入即可
object Demo4 {
def main(args: Array[String]): Unit = {
import Test._
print(person1(10))//dufu10
}
def person1(age:Int)(implicit name : String): String = name+age
}
object Test{
implicit val a: String ="dufu"
}
但是定义在class中是不行的
当然,定义在同一个object当然没问题的
object Demo4 {
implicit val a: String ="dufu"
def main(args: Array[String]): Unit = {
print(person1(10))//dufu10
}
def person1(age:Int)(implicit name : String): String = name+age
}
一个稍微复杂的例子
如下,可以看出,sortBy方法有一个隐式参数,类型为Ordering[B],
- 当B为内置类型时,比如String,会有内置的隐式参数完成
- 当B为自定义类时,比如下面的自定义类Girl,就需要自己实现这个隐式参数(或者说自己创建这个隐式参数)
def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Repr
object SortDemo2 extends App {
val conf: SparkConf = new SparkConf().setAppName("wordcount").setMaster("local")
val sc = new SparkContext(conf)
val rdd: Array[Girl] = Array(Girl(10, 156), Girl(6, 136), Girl(7, 176), Girl(9, 196))
import Girl._
//sortBy有一个隐式参数
rdd.sortBy(x => x)(Ordering[Girl]).foreach(println)
}
case class Girl(beauty: Int, height: Int) {
}
object Girl {
//定义一个隐式变量,别看a这么多代码,本质也是个变量
implicit val a: Ordering[Girl] = new Ordering[Girl]() {
//实现compare方法
override def compare(x: Girl, y: Girl): Int = {
val rs: Int = y.beauty - x.beauty
if (rs == 0) {
return y.height - x.height
}
rs
}
}
}
换种写法,但是一般不这么写,隐式的参数,就是不想让你显式的传入.
object SortDemo2 extends App {
val conf: SparkConf = new SparkConf().setAppName("test").setMaster("local")
val sc = new SparkContext(conf)
val rdd: Array[Girl] = Array(Girl(10, 156), Girl(6, 136), Girl(7, 176), Girl(9, 196))
//直接传入隐式参数.哪里需要就在哪里创建
rdd.sortBy((x: Girl) => x)(new Ordering[Girl]() {
//实现compare方法
override def compare(x: Girl, y: Girl): Int = {
//依据颜值进行排序
val rs: Int = y.beauty - x.beauty
if (rs == 0) {
//颜值相同情况下依据身高进行排序
return y.height - x.height
}
rs
}
}).foreach(println)
}
//创建自定义类Girl
case class Girl(beauty: Int, height: Int) {
}
再比如
object _SortDemo {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setAppName("wordcount").setMaster("local")
val sc = new SparkContext(conf)
//创建5个学生的数组
val stus: Array[Student] = Array(Student(1001, "zhangsan", 23, "f"),
Student(1003, "lisi", 12, "f"),
Student(1002, "wangwu", 40, "m"),
Student(1002, "zhaoliu", 18, "f"),
Student(1004, "niubi", 7, "m"))
val stts: RDD[Student] = sc.parallelize(stus)
val sorted: RDD[Student] =stts.sortBy(x =>x)
sorted.foreach(println)
}
}
case class Student(sid: Int, name: String, age: Int, gender: String) {}
object Student {
//定义一个隐式变量,可以用于某些需要隐式参数的方法,当然,前提是类型匹配
implicit val suibian: Ordering[Student] =new Ordering[Student]{
override def compare(x: Student, y: Student): Int = {
val rs: Int =x.sid-y.sid
if(rs==0){
return x.age-y.age
}
rs
}
}
}
隐式参数的选择依据其类型
abstract class Monoid[A] {
def add(x: A, y: A): A
def unit: A
}
object ImplicitTest {
//定义隐式变量,可以用于含有隐式参数的方法. 类型匹配的前提下
implicit val stringMonid: Monoid[String] = new Monoid[String] {
override def add(x: String, y: String): String = {
x + y
}
override def unit: String = ""
}
//定义隐式变量,可以用于含有隐式参数的方法. 类型匹配的前提下
implicit val intMoninew: Monoid[Int] = new Monoid[Int] {
override def add(x: Int, y: Int): Int = {
x + y
}
override def unit: Int = 0
}
//定义隐式变量,可以用于含有隐式参数的方法. 类型匹配的前提下
implicit val doubleMon: Monoid[Double] = new Monoid[Double] {
override def add(x: Double, y: Double): Double = x + y
override def unit: Double = 0.0
}
//定义一个含有隐式参数的方法
def sum[A](xs: List[A])(implicit m: Monoid[A]): A = {
if (xs.isEmpty) m.unit
else m.add(xs.head, sum(xs.tail))
}
def main(args: Array[String]): Unit = {
//依据参数类型自动选择隐式参数
println(sum(List(1, 2, 3))) // 6
println(sum(List("a", "b", "c"))) //abc
println(sum(List(1.0, 2.0, 3.4))) //6.4
}
}
也可以将隐式变量写在不同的object中,使用的时候导入即可
//隐式参数demo
abstract class Monoid[A] {
def add(x: A, y: A): A
def unit: A
}
object ImplicitTest {
implicit val stringMonid: Monoid[String] = new Monoid[String] {
override def add(x: String, y: String): String = {
x + y
}
override def unit: String = ""
}
implicit val intMoninew: Monoid[Int] = new Monoid[Int] {
override def add(x: Int, y: Int): Int = {
x + y
}
override def unit: Int = 0
}
implicit val doubleMon: Monoid[Double] = new Monoid[Double] {
override def add(x: Double, y: Double): Double = x + y
override def unit: Double = 0.0
}
def sum[A](xs: List[A])(implicit m: Monoid[A]): A = {
if (xs.isEmpty) m.unit
else m.add(xs.head, sum(xs.tail))
}
}
object test extends App {
//导入隐式参数
import ImplicitTest._
println(sum(List(1, 2, 3))) // 6
println(sum(List("a", "b", "c"))) //abc
println(sum(List(1.0, 2.0, 3.4))) //6.4
}