scala 隐式参数入门及应用

定义一个方法,其中包含一个隐式参数. 那么调用的时候可以不用把这个隐式参数传进去, 解释器会自己找一个用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
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值