zoukankan      html  css  js  c++  java
  • Scala之隐式转换implicit详解

    假设我们有一个表示文本的行数的类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
    让我们看看在编译时加入 “-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就会变为一个整型。
     
    转自:http://blog.csdn.net/nethibernate/article/details/5893184
  • 相关阅读:
    第07组 Alpha冲刺(1/6)
    第07组 团队Git现场编程实战
    团队项目-需求分析报告
    团队项目-选题报告
    第07组 Alpha冲刺(4/6)
    第07组 Alpha冲刺(3/6)
    第07组 Alpha冲刺(2/6)
    第07组 Alpha冲刺(1/6)
    第07组 团队Git现场编程实战
    第07组 团队项目-需求分析报告
  • 原文地址:https://www.cnblogs.com/likai198981/p/4166673.html
Copyright © 2011-2022 走看看