有時候咱們看scala代碼的時候,會發現明明沒有這個類的類型或者函數,甚至是沒有這個類,編譯器不只沒有報錯,程序還能夠正常運行,其實這裏就用到了scala的隱式轉換。函數
當咱們調用一個對象的方法的時候,可是這個對象並無這個方法,此時就會觸發隱式轉換,會把這個對象偷偷的轉換爲具備這個方法的對象。
好比下面的例子,小雞能夠走路也能夠跑,可是它也想像小鳥同樣飛,可是它有沒有這個功能。咱們能夠在不對小雞整改的基礎上,引入ChickenImplicit,讓小雞能夠隱式的調用Bird的fly方法,讓它能夠像小鳥同樣飛。scala
object ImplicitDemo1 { def main(args: Array[String]): Unit = { import ChickenImplicit._ val chicken = new Chicken() chicken.work() chicken.run() // 隱式轉爲Bird,並調用Bird的fly方法 chicken.fly() } } class Chicken() { def work(): Unit = { println("小雞在走") } def run(): Unit = { println("小雞在跑") } } class Bird { def fly(): Unit = { println("小鳥在飛") } } object ChickenImplicit { implicit def chicken2Bird(c: Chicken): Bird = new Bird() }
上面是額外的定義ChickenImplicit,可是有時候咱們能夠直接在同一個類裏定義,這樣局不用加import,具體用哪一種仍是要看實際場景。code
object ImplicitDemo2 { def main(args: Array[String]): Unit = { val chicken = new Chicken2() chicken.work() chicken.run() // 隱式轉爲Bird,並調用Bird的fly方法 chicken.fly() } implicit def chicken2Bird(c: Chicken2): Bird2 = new Bird2() } class Chicken2() { def work(): Unit = { println("小雞在走") } def run(): Unit = { println("小雞在跑") } } class Bird2 { def fly(): Unit = { println("小鳥在飛") } }
好比咱們要調用方法,打印咱們傳遞的參數,咱們是這樣寫的:對象
def main(args: Array[String]): Unit = { printInfo1("aaa") // aaa } def printInfo1(str: String): Unit = { println(str) }
若是咱們調用方法的時候,若是不想傳遞參數,咱們能夠這樣:
在方法裏指定默認值ci
def main(args: Array[String]): Unit = { printInfo2("bbb") // bbb printInfo2() // default } def printInfo2(str: String = "default"): Unit = { println(str) }
若是經過隱式參數,那咱們就能夠這樣:
這裏的方法不加括號也是能夠的。因爲是經過類型來匹配隱式值的,因此在一個做用域中,同一個類型只能有一次,而且他的優先級高於默認的,因此沒有傳遞參數的時候,打印的implicit。作用域
def main(args: Array[String]): Unit = { implicit val str: String = "implicit" printInfo3("ccc") // ccc printInfo3() // default printInfo3 // implicit } def printInfo3(implicit str: String = "default"): Unit = { println(str) }
當咱們須要隱式轉換的時候,咱們就須要用implicit
關鍵字。
隱式轉換的時候,他會先全局的查找是否有匹配的方法或者參數,若是沒有再考慮隱式轉換。
因爲隱式參數是根據類型的,因此同一做用域不能定義多個同一個類型的,而且默認值是優先於默認的。編譯器