scala的隐式转换学习总结(详细)

scala的隐式转换学习总结(详细)scala隐式转换,详细介绍

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

一,隐式转换函数

     1, 格式,           

implicit def 函数名(参数):返回值类型={
     //函数体
     //返回值
}

     2,例子:

//导入对应的规则类,以免出现警告
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
//定义将Int类型的值转换为Float的函数
scala> implicit def int2float(x:Int): Float = x.toFloat
int2float: (x: Int)Float

scala> val x:Float = 2
x: Float = 2.0
scala>

  3,注意事项:

      1) 隐式转换函数的函数名可以是任意的,与函数名称无关,只与函数签名(函数参数和返回值类型)有关。

      2)如果当前作用域中存在函数签名相同但函数名称不同的两个隐式转换函数,则在进行隐式转换时会报错。

//函数一
scala> implicit def int2float2(x: Float): Int = x.toInt
int2float2: (x: Float)Int
//函数二
scala> implicit def int2float(x: Float): Int = x.toInt
int2float: (x: Float)Int
//调用,报错
scala> val x:Int = 2.55f
<console>:14: error: type mismatch;
 found   : Float(2.55)
 required: Int
Note that implicit conversions are not applicable because they are ambiguous:
 both method int2float2 of type (x: Float)Int
 and method int2float of type (x: Float)Int
 are possible conversion functions from Float(2.55) to Int
       val x:Int = 2.55f
                   ^

 二,隐式类与隐式对象

    1,隐式类:通过在类名前使用 implicit 关键字定义

         1)格式:

implicit class 类名(参数){
    //类主体
}

 例子:string中没有bark方法,通过隐式转换,调用对应的方法转换

scala> implicit class Dog(val name: String){
     | def bark=println(s"$name is barking")}
defined class Dog

scala> "barkdo".bark
barkdo is barking

 2)注意事项: 隐式类的主构造函数参数有且仅有一个!之所以只能有一个参数,是因为隐式转换是将一种类型转换为另外一种类型,源类型与目标类型是一一对应的

scala> implicit class Dog2(val name: String, val age: Int){
     | def bark=println(s"$name is barking")}
<console>:15: error: implicit classes must accept exactly one primary constructor parameter
       implicit class Dog2(val name: String, val age: Int){
  
  

    2  隐式对象

        格式:

implicit object 对象名{
    //类主体
}

      例子

object ImplicitTest extends App{
   //定义一个trait Multiplicable
  trait Multiplicable[T]{
     def multiply(x: T):T
   }
  //定义一个隐式对象,用于整型数据相乘
  implicit object MultiplicableInt extends Multiplicable[Int]{
    def multiply(x: Int): Int = x*x
  }
  //定义一个用于字符串相乘的隐式对象
  implicit object MultiplicableString extends Multiplicable[String]{
    def multiply(x: String): String = x*2
  }
  //定义一个函数,函数具有泛型参数
  def multiply[T: Multiplicable](x: T): T ={
    //implicitly方法,访问隐式对象
    val ev = implicitly[Multiplicable[T]]
    //根据具体的类型调用相应的隐式对象中的方法
    ev.multiply(x)
  }

  //调用隐式对象 MultiplicableInt 中的方法
  println(multiply(5))

  //调用隐式对象 MultiplicableString 中的方法
  println(multiply("5"))
}

 运行结果:

25
55

三,隐式参数与隐式值

   1, 隐式参数,在函数的定义时,在参数前添加implicit关键字。

      格式:

def 函数名(implicit 参数名:l类型):返回值={
       //函数体
}

  例子://修改上面的一个方法

 //定义一个函数,函数具有泛型参数
  def multiply[T: Multiplicable](x: T)(implicit ev: Multiplicable[T]): T ={
    //根据具体的类型调用相应的隐式对象中的方法
    ev.multiply(x)
  }

 2)隐式值:

      格式

implicit val 变量名:类型=值

    例子

//定义一个带隐式参数的函数
scala> def sqrt(implicit x: Double) = Math.sqrt(x)
sqrt: (implicit x: Double)Double
//定义一个隐式值
scala> implicit val x:Double = 2.55
x: Double = 2.55
//调用定义的sqrt函数,它将自行调用定义好的隐式值
scala> sqrt
res1: Double = 1.5968719422671311

    3,隐式参数使用的常见问题:

      1)当函数没有柯里化时,implicit关键字会作用于函数列表中的的所有参数。

      2)隐式参数使用时要么全部不指定,要么全不指定,不能只指定部分。
      3)同类型的隐式值只能在作用域内出现一次,即不能在同一个作用域中定义多个相同类型的隐式值。

      4)在指定隐式参数时,implicit 关键字只能出现在参数开头。

      5)如果想要实现参数的部分隐式参数,只能使用函数的柯里化,

          如要实现这种形式的函数,def test(x:Int, implicit  y: Double)的形式,必须使用柯里化实现:def test(x: Int)(implicit y: Double).

       6) 柯里化的函数, implicit 关键字只能作用于最后一个参数。否则,不合法。

       7)implicit 关键字在隐式参数中只能出现一次,柯里化的函数也不例外!

scala> def product(implicit x: Double, implicit y: Double)=x*y
<console>:1: error: identifier expected but 'implicit' found.
def product(implicit x: Double, implicit y: Double)=x*y
scala> def product(implicit x: Double)(implicit y: Double)=x*y  //柯里化函数
<console>:1: error: '=' expected but '(' found.
def product(implicit x: Double)(implicit y: Double)=x*y

   8)匿名函数不能使用隐式参数

scala> val prodeuct = (x: Double, y: Double) => x*y
prodeuct: (Double, Double) => Double = <function2>

scala> val prodeuct = (implicit x: Double, y: Double) => x*y
<console>:1: error: '=>' expected but ',' found.
val prodeuct = (implicit x: Double, y: Double) => x*y
                                  ^

  9)柯里化的函数如果有隐式参数,则不能使用其偏应用函数

  

//柯里化函数product
scala> def product(x: Double)(y: Double)=x*y
product: (x: Double)(y: Double)Double
//两个参数的偏应用函数
scala> val p1=product _
p1: Double => (Double => Double) = <function1>
//调用
scala> p1(3.0)(4.0)
res1: Double = 12.0
//一个参数的偏应用函数
scala> val p2 = product(3.0) _
p2: Double => Double = <function1>
//调用
scala> p2(4.0)
res2: Double = 12.0
//将柯里化函数参数y, 声明为隐式参数
scala> def product(x: Double)(implicit y: Double)=x*y
product: (x: Double)(implicit y: Double)Double
//定义隐式参数后,便不能使用其偏应用函数
scala> val p1=product _
<console>:13: error: could not find implicit value for parameter y: Double
       val p1=product _
              ^
scala>

四,隐式函数的若干规则:

      1)显示定义规则

             在使用带有隐式参数的函数时,如果没有明确指定与参数类型匹配相同的隐式值,编译器不会通过额外的隐式转换来确定函数的要求。

      2)作用域规则

            不管是隐式值,隐式对象,隐式类或隐式转换函数,都必须在当前的作用域使用才能起作用!

      3)无歧义规则

             所谓无歧义值的是,不能存在多个隐式转换是代码合法,如代码中不应该存在两个隐式转换函数能够同时使某一类型转换为另一类型,也不应该存在相同的两个隐式值,主构造函数参数类型以及成员方法等同的两个隐式类。

     4)一次性转换规则

             隐式转换从源类型到目标类型只会经过一次转换,不会经过多次隐式转换达到。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/183287.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 哈佛结构和普林斯顿结构的区别_普林斯顿大学和哈佛大学哪个更厉害

    哈佛结构和普林斯顿结构的区别_普林斯顿大学和哈佛大学哪个更厉害哈佛结构是一种将程序指令存储和数据存储分开的存储器结构。中央处理器首先到程序指令存储器中读取程序指令内容,解码后得到数据地址,再到相应的数据存储器中读取数据,并进行下一步的操作(通常是执行)。程序指令存储和数据存储分开,可以使指令和数据有不同的数据宽度,如Microchip公司的PIC16芯片的程序指令是14位宽度,而数据是8位宽度。      哈佛结构的微处理器通常具有较高的执行效

    2022年10月5日
    0
  • 商品分类递归查询Tree结构展示

    商品分类递归查询Tree结构展示

    2021年7月11日
    62
  • Java Calendar 日历类的时间操作 Timestamp Date Calendar 相互转换

    Java Calendar 日历类的时间操作 Timestamp Date Calendar 相互转换JavaCalendar日历类的时间操作,这也许是Java环境下创建和管理日历及操作时间最简单的一个方案了,示范代码也很简单。演示了获取时间,日期时间的累加和累减,以及日期时间的比较。原文地址:blog.csdn.net/joyous/article/details/9630893注意事项:Calendar的month从0开始,也就是全年12个月由0~1…

    2022年4月26日
    53
  • 计算机病毒的活性,计算机病毒的特性

    计算机病毒的活性,计算机病毒的特性计算机病毒一般具有以下特性:1.计算机病毒的程序性(可执行性)计算机病毒与其他合法程序一样,是一段可执行程序,但它不是一个完整的程序,而是寄生在其他可执行程序上,因此它享有一切程序所能得到的权力。在病毒运行时,与合法程序争夺系统的控制权。计算机病毒只有当它在计算机内得以运行时,才具有传染性和破坏性等活性。也就是说计算机CPU的控制权是关键问题。若计算机在正常程序控制下运行,而不运行带病毒的程序,…

    2022年5月27日
    28
  • FEC介绍(一)_FEC项目是什么意思

    FEC介绍(一)_FEC项目是什么意思1、FEC是什么。FEC,forwarderrorcorrection,前向纠错。2、FEC用来做什么。网络数据传输时,难免出现数据包丢失等问题。数据传输出现丢包时,常用的传输方式有2种:丢包重传和前向纠错(FEC)。丢包重传是接收方发现数据包有丢失,请求发送方重新发包。帧头信息中的sequencenumber,正常状态下,该序列号是连续的。接收方根据该序列号判断是否丢包。可以看出,丢包重传是接收方和发送方本身有几次交互。FEC通过另外一种方式处理丢包。发送方在发送数据时,在每

    2022年8月11日
    5
  • dataframe填充缺失值_pandas填充空值

    dataframe填充缺失值_pandas填充空值如果单独是>>>df.fillna(0)>>>print(df)#可以看到未发生改变>>>print(df.fillna(0))#如果直接打印是可以看到填充进去了>>>print(df)#但是再次打印就会发现没有了,还是Nan将其Nan全部填充为0,这时再打印的话会发现根本未填充,这是因…

    2022年8月12日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号