1. 程式人生 > >Scala 檢視界定

Scala 檢視界定

Scala 檢視界定,有些書上寫的太簡,很多細節都沒有寫到。
先從隱式轉換說
隱式轉換的啟動時機:
     掉用成員時 (包括成員變數,成員方法)
     傳引數時 (實際傳入的引數型別與預期的引數型別(宣告方法時設定的引數型別)不一致)
     隱式轉換函式或引數都是存在源(指當前的class)或當前目標的伴生物件中
     

檢視界定:

**************************************案例一**********************************************
package paramtype

class ViewBoundTwo {
  def vbt()={
    println("this is vbt")
  }
}


package paramtype

class ViewBoundOne {
       implicit def vo[T](a: T)={
         new ViewBoundTwo
       }
       def say[T](a: T)={
         a.vbt()
       }
}

object ViewBoundOne{
  def main(args: Array[String]): Unit = {
    var vbo = new ViewBoundOne
    vbo.say()
  }
}


**************************************案例二********************************************** 
   
   
package paramtype

class ViewBoundTwo {
  def vbt()={
    println("this is vbt")
  }
}


package paramtype

class ViewBoundOne {

       def say[T](a: T)(implicit f: T=>ViewBoundTwo )={
         a.vbt()
       }
}

object ViewBoundOne{
  implicit def vo[T](a: T)={
    new ViewBoundTwo
  }
  def main(args: Array[String]): Unit = {
    var vbo = new ViewBoundOne
    vbo.say()
  }
}   

   
   
   
**************************************案例三**********************************************  
package paramtype

class ViewBoundTwo {

  def vbt()={
    println("this is vbt")
  }
}

object ViewBoundTwo{
  implicit def vo[T](a: T)={
    new ViewBoundTwo
  }
}


package paramtype

class ViewBoundOne {

       def say[T](a: T)(implicit f: T=>ViewBoundTwo )={
         a.vbt()
       }
}
object ViewBoundOne{
import paramtype.ViewBoundTwo._
  def main(args: Array[String]): Unit = {
    var vbo = new ViewBoundOne
    vbo.say()
  }
}  
   
   
**************************************案例三檢視界定**********************************************   

package paramtype

class ViewBoundTwo {

  def vbt()={
    println("this is vbt")
  }
}

object ViewBoundTwo{          //objec伴生物件中編寫一個隱式函式
  implicit def vo[T](a: T)={
    new ViewBoundTwo
  }
}
   
package paramtype

class ViewBoundOne[T <% ViewBoundTwo] {

       def say(a: T)={
         a.vbt()
       }
}

object ViewBoundOne{
 
  def main(args: Array[String]): Unit = {
    var vbo = new ViewBoundOne[String]
    vbo.say("a")
  }
}

**************************************案例四檢視界定**********************************************  
package paramtype

class ViewBoundTwo {

  def vbt()={
    println("this is vbt")
  }
}

object ViewBoundTwo{// ViewBoundTwo 伴生物件中沒有隱式函式

}

package paramtype

class ViewBoundOne[T <% ViewBoundTwo] {

       def say(a: T)={
         a.vbt()
       }
}
object ViewBoundOne{ //ViewBoundOne 伴生物件中編寫一個隱式函式
  implicit def vo[T](a: T)={
    new ViewBoundTwo
  }
  def main(args: Array[String]): Unit = {
    var vbo = new ViewBoundOne[String]
    vbo.say("a")
  }
}

檢視界定是指  T型別可以隱式的轉換為  ViewBoundTwo型別,前提條件是在當前目標的伴生物件中或源伴生物件中必須要存在一個 
implicit def obj2obj[T](a: T)={
   new ViewBoundTwo
  } 
這樣的隱式轉換函式。
主語事項:此時在class ViewBoundOne[T <% ViewBoundTwo] 中的方法中不能顯示的出現 (implicit f: T=>ViewBoundTwo)柯理化
例如: 
     def hel(a: T)(implicit f: T=> ViewBoundTwo )={
         a.vbt()  //這裡會報錯。因為 T <% ViewBoundTwo 本身就是表達 T 型別可以隱隱式轉換成ViewBoundTwo 型別,
                  //兩者的意義是相同的,會形成重複衝突,沒有必要。
       }


**************************************案例五注意柯理化宣告隱式函式********************************************** 


package paramtype

class ViewBoundTwo {

  def vbt()={
    println("this is vbt")
  }
}

object ViewBoundTwo{

}


package paramtype

class ViewBoundOne[T] {
  implicit def vo[T](a: T)={  //隱式函式 然也可以匯入包含此隱式函式的引用  沒有實際意義
    new ViewBoundTwo
  }
       def say(a: T)={
         a.vbt()
       }
       def hel(a: T)(implicit f: T=> ViewBoundTwo )={
         a.vbt()
       }
}
object ViewBoundOne{
  implicit def vo[T](a: T)={  //隱式函式 當然也可以匯入包含此隱式函式的引用 沒有實際意義
    new ViewBoundTwo
  }
  def hel[T](a: T)(implicit f: T=> ViewBoundTwo )={
    a.vbt()
  }
  def main(args: Array[String]): Unit = {
    var vbo = new ViewBoundOne[String]
    vbo.say("a")
    hel("s")
  }
}

這個案例你可以看到,在class 中和 object 中 都存在相同的隱式函式 vo,因為在柯理化宣告隱式函式的地方必須要保證
此class或object存在對應的實際隱式函式。(implicit f: T=> ViewBoundTwo ) 就是表示此class或object 存在一個實際的
隱式函式 implicit def f‘別名隨意’ (a: T)={
      new ViewBoundTwo
}
隱式轉換的目的就是可以 使當前型別A的引數 可以訪問另一種型別B的成員。但是不可以訪問B的子類成員。成員:包括成員變數成員方法。