`
beike
  • 浏览: 362777 次
社区版块
存档分类
最新评论

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

 
阅读更多

转 http://blog.csdn.net/nethibernate/article/details/5893184

在学习Scala的时候,隐式转换(implicit conversion)这个特性让我实在是闹不住啊。于是乎一边试用一边感慨:真的是太强大,太方便了。

不过,越是强大且方便的东西,越容易用出毛病来。在我不求甚解的情况下,毛病就来了,我把它称为隐式转换优先顺序问题:

 

假设我们有一个表示文本的行数的类LineNumber:

 

class LineNumber ( val num : Int ) 

 

我们可以用这个类来表示一本书中每一页的行数:

 

val lineNumOfPage1 = new LineNumber(112)
val lineNumOfPage2 = new LineNumber(120)


上面的代码分别表示了第一页和第二页的行数。当然,我们也应该可以将它们相加,得到这两页的总行数:

val totalLineNum = lineNumOfPage1 + lineNumOfPage2

 

这样的话,我们的LineNumber类里就应该有一个 “+” 方法来将两个对象相加:

 

class LineNumber ( val num : Int ) {
  
  def + ( that : LineNumber ) = new LineNumber( this.num + that.num )

}


从直观上讲,我们甚至可以直接用整数来和LineNumber相加:

val totalLineNumber = lineNumOfPage1 + 120

//或者

val totalLineNumber = 112 + lineNumOfPage2

 

写到这里我们发现,LineNumber对象中没有接受整型作为参数的 “+” 方法;而整型中也不会有接受LineNumber作为参数的 “+” 方法。

 

为了说明问题,我们不在LineNumber类中增加一个整型作为参数的重载方法,而是定义两个隐式转换,一个将Int转换为LineNumber,另一个将LineNumber转换为Int:

 

object LineNumber{
  
  implicit def intToLineNumber( i : Int ) = new LineNumber(i)

  implicit def lineNumberToInt( o : LineNumber ) = o.num

}


接下来再让我们尝试用LineNumber和整型相加:

import LineNumber._

val totalLineNumber1 = lineNumOfPage1 + 120

val totalLineNumber2 = 112 + lineNumOfPage2


我们会得到什么结果呢?

我最初认为,Scala编译器可能会产生编译错误,毕竟我们现在的代码中对于两种类型的隐式转换都是存在的,这样的话上面两个语句的方法参数和调用方法的对象都可以做隐式转换。很明显我错了。运行结果:totalLineNumber1是一个新的LineNumber的对象,并且它的字段num会是232;而totalLineNumber2则是一个Int类型,值为232。

先让我们看看在编译时加入 “-Xprint:typer” 后上面两句的结果:

 

val totalLineNumber1: LineNumber = lineNumOfPage1.+(LineNumber.intToLineNumber(120));

val totalLineNumber2: Int = 112.+(LineNumber.lineNumberToInt(lineNumOfPage2));


到这里已经很清楚了。Scala编译器优先选择了方法的参数作为转换对象,而没有选择调用方法的对象。这是为什么呢?

其实,当程序类型检查出现问题的时候,Scala编译器会在两个位置上对出现问题的语句尝试使用隐式转换:

 

  • 第一个位置是 “可以直接将某个类型转换为期望的类型” 的地方
  • 第二个位置是 “可以将调用方法的对象转换为合适类型” 的地方


第一个位置是那种我们需要A但是传入的却是B的地方。上面的例子正好就是这样的情况,对于totalLineNumber1来说,lineNumOfPage1的 “+” 方法需要的参数类型是LineNumber型,然而我们传入的是Int类型,Scala编译器在这里检测到类型错误后,会寻找将Int转换为LineNumber的隐式转换。因为在代码开始时,我们利用 "import LineNumber._ " 导入了相应的隐式转换,因此Scala编译器使用导入的隐式转换将整型120转换为了LineNumber类型。totalLineNumber2发生的情况是相同的,只不过是将LineNumber类型转换为了Int类型。

也就是说,Scala编译器在使用隐式转换的时候,首先回去寻找可以直接转换类型的位置,其次才对调用方法的对象。如果我们将我们的隐式转换中intToLineNumber的转换去掉,那么我们得到的totalLineNumber1就会变为一个整型。


就像我开头所说的那样,Scala的隐式转换是一个非常强大的工具,但是如果不了解它,或者将其滥用在程序中,会使得程序难以理解和维护。真的到了那个时候,就确实“闹不住”了。

 

分享到:
评论

相关推荐

    alg-net-cala-config:Net-Installer的Calamares配置

    在"alg-pure-cala-config"中,“pure”可能暗示了一种纯净或者简洁的配置方式,可能意味着这个配置专注于最基本的、不受额外软件或设置干扰的安装体验。这可能是为了确保安装过程的稳定性和效率,避免因不必要的组件...

    微机原理电科

    【微机原理】是计算机科学中的基础课程,主要研究微型计算机的基本结构、工作原理和操作机制。这份期末考试试卷涵盖了微机原理的核心概念,包括微处理器、存储器寻址、中断系统、数据表示以及指令系统等多个方面。 ...

    S3cala:为Scala编写的非阻塞S3客户端

    S3cala Scala的非阻塞S3客户端用法该项目尚未投入生产; 使用风险自负。用法示例在内部,S3cala是AWS Java SDK的精简包装。 它使异步API适应使用Scala的 ,从而使其易于使用。 package org . example . s3calaimport...

    计算机组成原理实验三硬布线控制器实验.pdf

    2. 在单步模式下,分别执行ADD、PUSH、LDRA、CALA指令,记录其预期和实际的节拍顺序。比如ADD R1,R2的0012H操作码,实际观察到的节拍顺序是0000-0010-0011。 3. 选择不同指令组的指令,如MVRR、JMPA、CALR、IRET,...

    白光LED用红色发光材料CaLa2(MoO4)4:Eu3+的微波辅助溶胶–凝胶法合成及发光特性 (2015年)

    以柠檬酸为络合剂,采用微波辅助溶胶–凝胶法制备了CaLa2(MoO4)4:Eu3+红色荧光粉。研究了前驱体的热分解历程,分析表征了样品的结构、形貌和发光性能。探讨了焙烧温度、Eu3+掺杂量、柠檬酸与乙二醇摩尔比和硼酸用量等...

    河南省焦作市沁阳市第一中学2019_2020学年高一英语下学期第八次月考试题

    这篇资料主要介绍了西班牙四个美丽的海滩,分别是Cala de Algaiarens、Cala Tarida、Beach of La Concha和Sotavento,适合不同兴趣的游客。 1. Cala de Algaiarens位于Minorea,这个海滩以其柔软的金色沙滩和清澈的...

    scala-2.11.12.msi 安装程序

    Scala是一种强大的、现代的编程语言,它在IT领域中被广泛应用,特别是在大数据处理和分布式计算中,例如Apache Spark就是基于Scala开发的。标题中的"scala-2.11.12.msi"指的是Scala的特定版本2.11.12的Windows安装...

    Python_Midterm_Cala:Python中期存储库-Petr Chala-2021_06_04

    Python_Midterm_Cala Python中期存储库-PetrČala-2021_06_04 这是PetrČala编写和提交的Python数据处理-JEM207(LS2020 / 21)代码主题中期的存储库

    GSM常用AT指令列表与实例

    AT+CPBN:电话簿移动动作,移动电话簿中的条目前移或后移(按字母顺序)。 AT+CNUM:签署者号码。 AT+WAIP:防止在下一次重起时初始化所有的电话簿。 AT+WDCP:删除呼叫电话号码。 AT+CSVM:设置语音邮件号码。 六...

    微信dat文件解密还原工具【易语言】【含源代码】【含模块】

    【说明】电脑版微信用了一段时间之后,会在硬盘中存储大量以*.dat为扩展名存储的图像加密文件,占用了大量的空间。微信本身不提供甄别和删除这些图片文件的功能,因此编制一个可以将这些加密dat文件解密的程序,并将...

    山东省2020年上学期青岛第十九中学高一英语期中考试题[精选].doc

    文章中提到,Cala Tarida特别适合那些想要放松身心和享受清澈水域游泳的游客。由于靠近城市,这里同样对音乐节的爱好者和夜生活寻求者有着独特的吸引力。在解答题目的时候,学生们需要准确地捕捉到Cala Tarida的定位...

    ELISACalc.rar

    它支持多种回归分析方法,包括直线回归、二次和三次曲线回归以及Logistic曲线拟合,这些方法在生物学研究中广泛应用,特别是在酶联免疫吸附测定(ELISA)实验中。 直线回归是最基础的统计分析方法之一,用于探究两...

    adi-与平台无关的应用程序的超便携式硬件接口-Rust开发

    Blog Cala旨在成为Rust中bo Make便携式应用和视频游戏的“氧化重新实现”。 关于| 来源| 变更日志| 教程| Blog Cala旨在成为Flutter / GTK和SDL /其他SDL项目在一个库中的“氧化重新实现”! Flutter主要用于移动...

    TMS320C2000 DSP硬件结构2

    在TMS320C2000中,程序控制涉及对指令执行次序的管理,包括程序地址生成、流水线顺序执行、有条件和无条件的分支、调用、返回,以及指令重复和中断处理。 2.4.1.2 堆栈操作 堆栈是处理器内部用于临时存储数据的...

    汇编模拟 洗衣机

    在计算机科学与技术领域,特别是微机原理课程中,使用低级语言如汇编语言进行编程是基础技能之一。西南科技大学的学生们在微机原理课程设计中,通过汇编语言实现了一个模拟洗衣机的过程,这不仅加深了他们对汇编语言...

    WaveCom模块AT指令

    此命令用于移动电话簿中的条目,使得联系人按字母顺序排序。 **7. AT+CNUM** 此命令用于获取签约者的电话号码。 **8. AT+WAIP** 此命令用于防止在下次重启时初始化所有电话簿,确保电话簿信息不会被清除。 **9....

    易语言-画曲线模块及应用例程

    模块的使用很简单,基于画板来实现,在参数中指定相关参数,就能使用,非常简单便捷。 目前主要有五种图形:折线图、一维柱状图、多维对比柱状图、多边形(填充、非填充)、直方图(配套有直方图数据整理子程序) ...

Global site tag (gtag.js) - Google Analytics