scala13——S隱式轉換和隱式引數
阿新 • • 發佈:2018-12-12
Scala提供的隱式轉換和隱式引數功能,是非常有特色的功能。是Java等程式語言所沒有的功能。它可以允許你手動指定,將某種型別的物件轉換成其他型別的物件或者是給一個類增加方法。通過這些功能,可以實現非常強大、特殊的功能。
。
通常建議,僅僅在需要進行隱式轉換的地方,用import匯入隱式轉換方法,這樣可以縮小隱式轉換方法的作用域,避免不需要的隱式轉換。
1、隱式轉換
Scala的隱式轉換,其實最核心的就是定義隱式轉換方法,即 implicit conversion function
。
定義的隱式轉換方法,只要在編寫的程式內引入,就會被Scala自動使用。Scala會根據隱式轉換方法的簽名,在程式中使用到隱式轉換方法接收的引數型別定義的物件時,會自動將其傳入隱式轉換方法,轉換為另外一種型別的物件並返回。這就是“隱式轉換”。其中所有的隱式值和隱式方法必須放到object中。
不過使用Scala的隱式轉換是有一定的限制的: implicit關鍵字只能用來修飾方法、變數(引數)。 隱式轉換的方法在當前範圍內才有效。如果隱式轉換不在當前範圍內定義(比如定義在另一個類中或包含在某個物件中),那麼必須通過import語句將其匯入。
2、 隱式引數
隱式引數,指的是在函式或者方法中,定義一個用implicit修飾的引數,此時Scala會嘗試找到一個指定型別的,用implicit修飾的引數,即隱式值,並注入引數。 Scala會在兩個範圍內查詢: 當前作用域內可見的val或var定義的隱式變數; 一種是隱式引數型別的伴生物件內的隱式值;
3、隱式轉換方法作用域
(1)Scala預設會使用兩種隱式轉換,一種是源型別或者目標型別的伴生物件內的隱式轉換方法;一種是當前程式作用域內的可以用唯一識別符號表示的隱式轉換方法。
(2)如果隱式轉換方法不在上述兩種情況下的話,那麼就必須手動使用import語法引入某個包下的隱式轉換方法,比如import test._
4、隱式轉換的時機
當物件呼叫類中不存在的方法或成員時,編譯器會自動將物件進行隱式轉換 當方法中的引數的型別與目標型別不一致時 ,會進行隱式轉換。
5、相關案例
5.1 讓File類具備RichFile類中的read方法
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) } }
5.2 AutoMan打怪獸
class Man(val name:String)
class AutoMan(val name: String) {
def heat=print("奧特曼打怪獸")
}
object AutoMan{
//隱式轉換方法
implicit def manToAutoMan(man:Man)=new AutoMan(man.name)
def main(args: Array[String]) {
val hero=new Man("hero")
//Man具備了AutoMan的方法
hero.heat
}
}
5.3 員工領取薪水
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())
}