2019独角兽企业重金招聘Python工程师标准>>>

Scala Implicit Conversion

从一个简单例子出发,我们定义一个函数接受一个字符串参数,并进行输出

def func(msg: String): Unit = println(msg)

这个函数在func("11")调用时候正常,但是在执行func(11)或func(1.1)时候就会报error: type mismatch的错误。这个问题很好解决:

  1. 针对特定的参数类型,重载多个func函数,这个不难,传统JAVA中的思路,但是需要定义多个函数

  2. 使用超类型,比如使用AnyVal,Any,这样的话比较麻烦,需要在函数中针对特定的逻辑做类型转化,从而进一步处理

上面两个方法使用的是传统JAVA思路,虽然都可以解决该问题,但是缺点是不够简洁;在充满了语法糖的Scala中,针对类型转换提供了特有的implicit隐式转换的功能。

隐式转化是一个函数,可以针对一个变量在需要的时候自动的进行类型转换;针对上面的例子,我们可以定义intToString函数

def func(msg: String): Unit = println(msg)implicit def intToString(i: Int): String = i.toStringfunc("hello world!")
func(123)

运行并输出,

C:\WorkSpace6-scala\scala-train\src\com\usoft>scala implicit.scala

warning: there was one feature warning; re-run with -feature for details

one warning found

hello world!

123

此时在调用func(11)时候, scala会自动针对11进行intToString函数的调用, 从而实现可以在func函数已有的类型上提供了新的类型支持,这里有几点要说一下:

  1. 隐式转换的核心是from类型和to类型,至于函数名称并不重要;上面我们取为intToString,只是为了直观,int2str的功能是一样的;隐式转换函数只关心from-to类型之间的匹配,比如我们需要to类型,但是提供了from类型,那么相应的implicit函数就会调用 

  2. 隐式转换只关心类型,所以如果同时定义两个隐式转换函数,from/to类型相同,但是函数名称不同,这个时候函数调用过程中如果需要进行类型转换,就会报ambiguous二义性的错误,即不知道使用哪个隐式转换函数进行转换

上面我们看到的例子是将函数的参数从一个类型自动转换为一个类型的例子,在Scala中,除了针对函数参数类型进行转换以外,还可以对函数的调用者的类型进行转换。

比如A+B,上面我们谈到是针对B进行类型自动转换, 其实可以在A上做类型转换,下面我们拿一个例子来说明

class IntWritable(_value: Int) {var value = _valuedef +(that: IntWritable): IntWritable = {new IntWritable(that.value + value)}
}implicit def intToWritable(int: Int) = new IntWritable(int)
new IntWritable(10) + 10

上面我们首先定义了一个类:IntWritable,并为int提供了一个隐式类型转换intToWritable,从而可以使得IntWritable的+函数在原先只接受IntWritable类型参数的基础上,接受一个Int类型的变量进行运算,即new IntWritable(10) + 10可以正常运行

现在换一个角度将"new IntWritable(10) + 10" 换为"10 + new IntWritable(10)"会是什么结果呢?会报错误吗?

如下代码,

class IntWritable(_value: Int) {var value = _valuedef +(that: IntWritable): IntWritable = {new IntWritable(that.value + value)}
}implicit def intToWritable(int: Int) = new IntWritable(int)
//implicit def writableToInt(that: IntWritable) = that.value//val result1 = new IntWritable(10) + 10
val result2 = 10 + new IntWritable(10)//println(result1.getClass.getName)
println(result2.getClass.getName) //Main$$anon$1$IntWritable

按道理是应该报错误,首先一个Int内置类型的+函数,没有IntWritable这个参数类型;其次,我们没有针对 IntWritable 类型提供到 Int 的隐式转换,

即没有提供writableToInt的implicit函数。

但是结果是什么?

10 + new IntWritable(10) 是可以正常运行的,而且整个表达的类型为IntWritable,而不是Int,即Int的10被intToWritable函数隐式函数转换为IntWritable类型;

结论:隐式转换可以针对函数参数类型和函数对象进行类型转换;现在问题来了,看下面的例子

class IntWritable(_value: Int) {var value = _valuedef +(that: IntWritable): IntWritable = {new IntWritable(that.value + value)}
}implicit def intToWritable(int: Int) = new IntWritable(int)
implicit def writableToInt(that: IntWritable) = that.valueval result1 = new IntWritable(10) + 10
val result2 = 10 + new IntWritable(10)println(result1.getClass.getName) //Main$$anon$1$IntWritable
println(result2.getClass.getName) //int

在上面的IntWritable类的基础上,我们提供了两个隐式类型转换函数,即Int和IntWritable之间的双向转换;这样的情况下result1和result2两个变量的类型是什么?

答案:result1的类型为IntWritable, result2的类型Int;很好理解, result1中的Int类型的10被intToWritable隐式转换为IntWritable;而result2中的IntWritable(10)被writableToInt 隐式转换为Int类型;

你肯定会问?result2中为什么不是像上面的例子一样, 把Int类型的10隐式转换为IntWritable类型呢?原因就是隐式转换的优先级;

发生类型不匹配的函数调用时, scala会尝试进行类型隐式转换;首先优先进行函数参数的类型转换,如果可以转换, 那么就完成函数的执行; 否则尝试去对函数调用对象的类型进行转换; 如果两个尝试都失败了,就会报方法不存在或者类型不匹配的错误;

OK, Scala的隐式转换是Scala里面随处可见的语法。

================END================

转载于:https://my.oschina.net/xinxingegeya/blog/407324

Scala Implicit Conversion相关推荐

  1. Scala Implicit

    2019独角兽企业重金招聘Python工程师标准>>> 序:前段时间用spray的时候对于http请求的参数以及response的结果用json格式的时候遇到了一个隐式转换,又专门查 ...

  2. cala中隐式转换(implicit conversion)的优先顺序

    转 http://blog.csdn.net/nethibernate/article/details/5893184 在学习Scala的时候,隐式转换(implicit conversion)这个特 ...

  3. scala implicit 关键字用法总结

    综述 implicit 关键字是scala中一个比较有特点的关键字,他保证了scala在很多时候没有一些不必要的代码冗余,使得scala在很多时候看起来更加简洁,同时使得scala的一些库在设计的时候 ...

  4. Implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGB

    在使用xcode5 sdk iOS7环境,创建图形上下文进行图形绘制,合并,裁剪,特效处理等时避免不了使用如下方法创建位图: 在 iOS7以前,是使用如下方法创建的: CG_EXTERN CGCont ...

  5. no implicit conversion of nil into String

    一.Cocoapod 执行pod install命令时报错 [!] An error occurred while processing the post-install hook of the Po ...

  6. solidity智能合约implicit conversion异常

    问题场景 在使用^0.5.10版本的solidity时,如果使用this关键字会出现以下问题. 代码: require(tokenContract.balanceOf(this) >= _num ...

  7. Scala Implicit 详解

    Implicit 是 Scala 中一个很重要的特性,开始学习 Scala 之前一直以为它和 Java 差不多,然而真的看一些 Scala 的源码时却发现并没有想象中那么简单,所以准备写几篇文章来详解 ...

  8. scala implicit - implicit parameters spark 应用

    语法 class PreferredPrompt(val preference: String)object Greeter {def greet(name:String)(implicit prom ...

  9. Scala 隐式(implicit)详解

    文章正文 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 1.Spark 中 ...

最新文章

  1. [转]学习Objective-C: 入门教材
  2. CSS属性选择器和部分伪类
  3. bzoj1002 生成树计数 找规律
  4. Virtual PC 使用指南
  5. [MATLAB粒子模拟笔记]差分泊松方程求静电场分布
  6. DisplayPageBoundaries 打开word后自动将页面间空白隐藏 (auto+定时器)
  7. sublime text java 开发_Sublime Text 3搭建Java开发环境
  8. 通过Windows Visual Studio远程调试WSL2中的.NET Core Linux应用程序
  9. python基础版课件_python基础课件精编版.ppt
  10. 想玩转工业界机器学习?先学Spark吧
  11. 公开课视频-浅谈前端性能测试
  12. 如何通过Facebook幻灯片广告让销售量疯涨
  13. xp系统能不能安装mysql_win xp32位系统安装mysql详细步骤
  14. funcode坐标c语言,01 FunCode C 入门.doc
  15. matlab仿真AMI码变换,matlab编程
  16. SVD奇异值分解简述
  17. DMA小区漏损治理之武林秘籍
  18. Oracle用户密码输错次数超过后被锁定LOCKED(TIMED)
  19. 2014春晚小品《扶不扶》台词集锦
  20. 局域中找不到Synology (搜索不到NAS服务器)

热门文章

  1. 信息安全评论员18期
  2. python线性表和队列_[笔记]python数据结构之线性表:linkedlist链表,stack栈,queue队列...
  3. python人工智能方向面试准备_高薪直通车丨人工智能+Python面试经验分享(西安**思数据)...
  4. mysql 避免使用临时表_从日期范围中选择时防止MySQL使用临时表
  5. python 最小硬币数_程序以找到要在Python中达到目标的硬币组合数量
  6. python综合作业题目_python作业 1、2、3 题
  7. c++中把一个函数中的语句复制到另一个语句中报错_从底层看前端(十一)—— JavaScript语法:脚本,模块和函数体。...
  8. python解析雷达数据_【学习笔记】使用python带时间戳提取rosbag中的图像和雷达数据...
  9. 苹果发布会证实,他们把脸部检测技术和ARKit结合在了一起
  10. 健身环爆打老头环!超高难度击败boss,宫崎英高估计也想不到,代码+硬件教程已开源...