天天看點

scala快速入門系列【隐式轉換和隐式參數】

本篇作為scala快速入門系列的第三十七篇部落格,為大家帶來的是關于隐式轉換和隐式參數的内容。

scala快速入門系列【隐式轉換和隐式參數】

隐式轉換

Scala提供的隐式轉換和隐式參數功能,是非常有特色的功能。是Java等程式設計語言所沒有的功能。它可以允許你手動指定,将某種類型的對象轉換成其他類型的對象或者是給一個類增加方法。通過這些功能,可以實作非常強大、特殊的功能。

Scala的隐式轉換,其實最核心的就是定義隐式轉換方法,即implicit conversion function。定義的隐式轉換方法,隻要在編寫的程式内引入,就會被Scala自動使用。Scala會根據隐式轉換方法的簽名,在程式中使用到隐式轉換方法接收的參數類型定義的對象時,會自動将其傳入隐式轉換方法,轉換為另外一種類型的對象并傳回。這就是“隐式轉換”。其中所有的隐式值和隐式方法必須放到object中。

然而使用Scala的隐式轉換是有一定的限制的,總結如下:

  • implicit關鍵字隻能用來修飾方法、變量(參數)。
  • 隐式轉換的方法在目前範圍内才有效。如果隐式轉換不在目前範圍内定義(比如定義在另一個類中或包含在某個對象中),那麼必須通過

    import

    語句将其導。

隐式參數

所謂的隐式參數,指的是在函數或者方法中,定義一個用

implicit

修飾的參數,此時Scala會嘗試找到一個指定類型的,用

implicit

修飾的參數,即隐式值,并注入參數。

Scala會在兩個範圍内查找:

  • 目前作用域内可見的val或var定義的隐式變量;
  • 一種是隐式參數類型的伴生對象内的隐式值;

隐式轉換方法作用域與導入

(1)Scala預設會使用兩種隐式轉換,一種是源類型或者目标類型的伴生對象内的隐式轉換方法;一種是目前程式作用域内的可以用唯一辨別符表示的隐式轉換方法。

(2)如果隐式轉換方法不在上述兩種情況下的話,那麼就必須手動使用import文法引入某個包下的隐式轉換方法,比如

import test._

。通常建議,僅僅在需要進行隐式轉換的地方,用import導入隐式轉換方法,這樣可以縮小隐式轉換方法的作用域,避免不需要的隐式轉換。

隐式轉換的時機

(1)當對象調用類中不存在的方法或成員時,編譯器會自動将對象進行隐式轉換.

(2)當方法中的參數的類型與目标類型不一緻時

隐式轉換和隐式參數案例

① 隐式轉換案例一(讓File類具備RichFile類中的read方法)

package cn.itcast.implic_demo

import java.io.File
import scala.io.Source

object MyPredef{
  //定義隐式轉換方法
  implicit def file2RichFile(file: File)=new RichFile(file)
}
class RichFile(val f:File) {
  def read()=Source.fromFile(f).mkString
}
object RichFile{
  def main(args: Array[String]) {
    val f=new File("E://words.txt")
    //使用import導入隐式轉換方法
    import MyPredef._
    //通過隐式轉換,讓File類具備了RichFile類中的方法
    val content=f.read()
    println(content)
  }
}           

複制

② 隐式轉換案例二(超人變身)

package cn.itcast.implic_demo

class Man(val name:String)
class SuperMan(val name: String) {
  def heat=print("超人打怪獸")
}
object SuperMan{
  //隐式轉換方法
  implicit def man2SuperMan(man:Man)=new SuperMan(man.name)
  def main(args: Array[String]) {
      val hero=new Man("hero")
      //Man具備了SuperMan的方法
      hero.heat
  }
}           

複制

③ 隐式轉換案例三(一個類隐式轉換成具有相同方法的多個類)

package cn.itcast.implic_demo
class A(c:C) {
    def readBook(): Unit ={
      println("A說:好書好書...")
    }
}
class B(c:C){
  def readBook(): Unit ={
    println("B說:看不懂...")
  }
  def writeBook(): Unit ={
    println("B說:不會寫...")
  }
}
class C
object AB{
  //建立一個類的2個類的隐式轉換
  implicit def C2A(c:C)=new A(c)
  implicit def C2B(c:C)=new B(c)
}
object B{
  def main(args: Array[String]) {
    //導包
    //1. import AB._ 會将AB類下的所有隐式轉換導進來
    //2. import AB._C2A 隻導入C類到A類的的隐式轉換方法
    //3. import AB._C2B 隻導入C類到B類的的隐式轉換方法
    import AB._
    val c=new C
    //由于A類與B類中都有readBook(),隻能導入其中一個,否則調用共同方法時代碼報錯
    //c.readBook()
    //C類可以執行B類中的writeBook()
    c.writeBook()
  }
}           

複制

④ 隐式參數案例四(員工領取薪水)

package cn.itcast.implic_demo


object Company{
  //在object中定義隐式值    注意:同一類型的隐式值隻允許出現一次,否則會報錯
  implicit  val aaa="zhangsan"
  implicit  val bbb=10000.00
}
class Boss {
  //注意參數比對的類型   它需要的是String類型的隐式值
  def callName()(implicit name:String):String={
    name+" is coming !"
  }
  //定義一個用implicit修飾的參數
  //注意參數比對的類型    它需要的是Double類型的隐式值
  def getMoney()(implicit money:Double):String={
    " 當月薪水:"+money
  }
}
object Boss extends App{
  //使用import導入定義好的隐式值,注意:必須先加載否則會報錯
  import Company._
  val boss =new Boss
  println(boss.callName()+boss.getMoney())

}           

複制

本期的内容分享就到這裡了,喜歡的小夥伴們記得點個贊,持續關注喲~下期為大家介紹的是scala的Actor并發程式設計,敬請期待٩(๑>◡<๑)۶