Scala implicit 隐式转换总结

本文深入探讨Scala中的三种隐式转换:隐式参数与值、隐式函数及隐式类,通过具体代码示例解释如何在不同场景下应用这些特性,增强代码的灵活性和可读性。

在Scala中implicit 转换有三种:

1.隐式参数与隐式值

package com.demo

object ImplicitPram {
  //在作用域内,只能指定一个同类型的隐式参数。
  implicit val a = 100

  /**
    * 在参数前加上implicit 关键字,表示a,b都是隐式参数,在调用时,可以显示的调用如
    * test_Param(1,2),亦可test_Param方式调用。
    * @param a
    * @param b
    */
  def test_Param(implicit a:Int,b:Int): Unit ={

    println(s"a=$a,b=$b")
  }
	/**
    * 当部分参数为implicit参数时,需使用柯里化方式定义,且隐式参数在后面,调用时,可以只使用
    * 一个显示的参数,也可以同时使用隐式和非隐式参数。
    * @param name
    * @param a
    */
  def test_P2(name:String)(implicit  a:Int): Unit ={
    println(s"name=$name,a=$a")
  }

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

//    test_Param(1,2)   指明参数的调用
      test_Param            //使用隐式参数,此时参数a,b的值均为100
//    test_P2("hello")           //调用时,不使用隐式参数

    test_P2("hello")(10)  //同时传入显示参数,和隐式参数。
  }
}

2.隐式函数

package com.demo

/**
  * 定义一个鸟类,有一个方法fly
  * @param xname
  */
class  Bird(xname:String){
  val name = xname
  def fly(): Unit ={
    println(s"$name can fly ...")
  }
}

/**
  * 定义一个猪类
  * @param xname
  */
class Pig(xname:String){
  val name = xname
}

object ImplicitFun {

  /**
    * 定义一个函数,使用implicit修饰,同时参数传入猪的一个对象,返回值为鸟类
    *
    * 请注意:隐式函数只与参数类型,和返回类型有关,与函数名称无关,故在作用域内不能存在
    * 参数类型相同,返回类型不同的隐式转换函数。
    * @param p
    * @return
    */
  implicit def pigToBird(p:Pig):Bird={
    new Bird(p.name)
  }

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

      new Pig("pery").fly()
/*
    创建一个猪的对象,调用fly 方法,此时,猪的对象会先寻找自己的fly 方法,若自己没有,若发现其他类有fly 方法,则会在作用域内寻找
    是否有隐式函数将猪的类型转换为鸟的类型,若有,就可以调用鸟的fly 方法。
*/

  }
}

3.隐式类

package com.demo

/**
  * 定义一个猪对象
  * @param xname
  */


class Pig(xname:String){
  val name = xname
}


object ImplicitClass_demo {

  /**
    * 定义了一个隐式类,当一个对象调用它本身没有的方法和变量或常量时,若隐式类中有,
    * 就会调用隐式类的的变量或常量和方法。
    * 隐式类必须定义在类中,包对象,或伴生对象中,同时,构造器只能有一个参数,就是隐式调用的类型。同一包中,类中,
    * 或伴生对象中,不能出现构造器参数类型相同的隐式类。
    * @param pig
    */
  implicit class bird(pig:Pig){

    val ss = "blue sky"
    val name = pig.name
    def canFly(): Unit ={
      println(s"$name can fly ...")
    }
  }

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

    val pig = new Pig("pery")
    pig.canFly()   //猪对象调用canfly 方法,本身没有,实际调用的时bird 的方法
    println(pig.ss) //猪对象没有ss的常量,实际上调用的时bird 的ss常量。

  }

}

Scala转换是一种强大的语言特性,可让编译器在编译期间自动推导信息,从而减少代码量,让程序员省去复杂重复的代码,忽略冗长、过于细节的部分[^1]。以下为几种常见的Scala转换及使用方法: ### 函数 函数使用`implicit`关键字定义,编译器会在需要时自动调用,从而将一种类型转换为另一种类型。 ```scala // 定义函数 implicit def intToDouble(x: Int): Double = x.toDouble // 使用转换 val num: Double = 5 ``` ### 参数 在函数或方法中定义用`implicit`修饰的参数,Scala会尝试找到指定类型且用`implicit`修饰的对象(即值)并注入参数。查找位置为当前作用域内可见的`val`或`var`定义的变量,以及参数类型的伴生对象内的值。 ```scala object ImplicitOps3 { def main(args: Array[String]): Unit = { var myArray: Array[Int] = Array(5, 6, 45, 1, 8, 9, 25, 0, 4, 91) println("排序前:" + myArray.mkString("[", ",", "]")) var newArray = myArray.sortWith(_ < _) println("排序后:" + newArray.mkString("[", ",", "]")) implicit val ord = new Ordering[Int]() { override def compare(x: Int, y: Int): Int = y.compareTo(x) } newArray = myArray.sorted println("排序后:" + newArray.mkString("[", ",", "]")) } } ``` ### Scala 2.10 之后引入了类,使用`implicit`声明类可扩展类的功能。类所带的构造参数有且只能有一个,且必须被定义在“类”或“伴生对象”或“包对象”里。 ```scala object TestImplicitClass { implicit class MyRichInt(val self: Int) { def myMax(num: Int): Int = if (num > self) num else self def myMin(num: Int): Int = if (num > self) self else num } def main(args: Array[String]): Unit = { println(12.myMax(15)) println(12.myMin(15)) } } ``` ### 解析机制 首先会在当前代码作用域下查找实体(方法、类、对象),若查找失败,会继续在参数的类型的作用域里查找,类型的作用域指与该类型相关联的全部伴生对象以及该类型所在包的包对象[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值