1. 程式人生 > >scala的隱式轉換—底層實現

scala的隱式轉換—底層實現

關鍵字: jvm方法呼叫    方法簽名   唯一匹配

看了很多網上的教程  都差不多是你抄我 我抄你 而且說的都是表面的東西 沒有往深處挖掘 今天在結合jvm分析方法呼叫的時候 找到一個新的思路 感覺挺靠譜的 拿出來和大家分享一下 (這個對於隱式值的理解沒啥幫助 但是隱式類大大的幫助)

知道 jvm在進行方法呼叫的時候  有一個方法簽名的,什麼多型就是基於這個實現的  在java裡面 方法的簽名 都是唯一的 我們在java方法的呼叫過程中 不管是早繫結還是晚繫結 都是可以唯一確認的 找到對應的方法 在實際進行處理

在scala中(畢競是基於jvm)也不例外(例外也無所謂 照著這個思路下去 理解這個隱式轉換很容易的)在scala中的一切都是物件

一切行為都是方法 這就  但是方法必須是 唯一的 這就和jvm的方法呼叫聯絡上了  

但是 scala 這裡做了一些進步 在編譯器 從記憶體裡面 尋找方法的時候 提供了一個容錯機制 它從所在作用域內 儘可能的滿足程式碼的呼叫  並且在查詢對應方法 的時候 不是按照 java中那樣 方法簽名 嚴格匹配

舉個例子java中進行函式的呼叫 需要嚴格說明 類 引數 方法名 但是在scala 中 這些條件 不用全部滿足 只要滿足部分就可以了 編譯器會根據一部分資訊 自己去尋找唯一匹配的 方法簽名 從而完成呼叫

object Stringutils {
  implicit class StringImprovement(val s : String){   //隱式類
      def increment = s.map(x => (x +1).toChar)
  }
}
object  Main extends  App{
  import com.mobin.scala.implicitPackage.Stringutils._
  println("mobin".increment)
}

如下程式碼  "mobin".increment 這個方法簽名 可以定位到唯一的方法 StringImprovement.increment(String)

在比如

class SwingType{
  def  wantLearned(sw : String) = println("兔子已經學會了"+sw)
}
object swimming{
  implicit def learningType(s : AminalType) = new SwingType
}
class AminalType
object AminalType extends  App{
  import com.mobin.scala.Scalaimplicit.swimming._
  val rabbit = new AminalType
    rabbit.wantLearned("breaststroke")         //蛙泳
}

AnimalType 沒有方法 wantLearned 但是 我們把它看成一個整體rabbit.wantLearned("breaststroke") 這些資訊組合在一起

不是正好是swimming.learningType(AnimalType).wantLearned(string)的方法簽名嗎 

隱式值轉換也可以拿進來理解

bject ImplicitDefDemo {
  def foo(msg : String) = println(msg)
  implicit def intToString(x : Int) = x.toString
 // implicit def intToString2(x : Int) = x.toString
  def main(args: Array[String]) {
    foo(10)
  }
}

這個10 對應的唯一法簽名 不正是intToString麼

總結:

  scala隱式轉換的核心思想是 在編譯報錯的情況下  通過程式碼中給定的條件 從作用域中 通過一些已有的處理方式 對部分資料進行轉換 或者 通過模糊匹配找到合適的處理邏輯 從而完成功能 這是我結合jvm的方法呼叫的一個理解思路 貌似可以說的通  唯一加不進去的就是 那個隱式引數自動添加了 不過那個好理解 不用這麼複雜 就是從作用域中 拉一個唯一和符合的值過來 底層怎麼做的 暫時沒想到