隱式轉換函數是以implicit關鍵字聲明的帶有單個參數的函數。這種函數將會自動應用,java
將值從一種類型轉換爲另外一種類型。ide
implicit def a(d: Double) = d.toInt
//不加上邊這句你試試 val i1: Int = 3.5 println(i1)
若是須要爲一個類增長一個方法,能夠經過隱式轉換來實現。好比想爲 File 增長一個 read 方法,函數
能夠以下定義:spa
import java.io.File import scala.io.Source class RichFile(val from: File) { def read = Source.fromFile(from.getPath).mkString } object Main1 extends App{ implicit def file2RichFile(from: File) = new RichFile(from) val contents = new File("D:\\Data\\Scala\\隨堂筆記\\筆記").read println(contents) }
有什麼好處呢?好處就是你能夠不修改原版本的代碼而爲本來的代碼增長新功能。scala
將name變量標記爲implicit,因此編譯器會在方法省略隱式參數的狀況下去搜索做用域內的隱式值做爲缺乏參數。code
implicit val name = "Nick"
def person(implicit name: String) = name println(person) //Nick
可是若是此時你又相同做用域中定義一個隱式變量,再次調用方法時就會報錯:對象
implicit val name = "Nick" implicit val name2 = "Nick"
def person(implicit name: String) = name println(person) //報錯!
1) 隱式轉換爲目標類型:把一種類型自動轉換到另外一種類型blog
def foo(msg : String) = println(msg)
implicit def intToString(x : Int) = x.toString foo(10)
2) 隱式轉換調用類中本不存在的方法ci
class Dog { val name = "金毛" } class Skill{ def fly(animal: Dog, skill: String) = println(animal.name + "已領悟" + skill) } object Learn{ implicit def learningType(s : Dog) = new Skill } object Main2 extends App{ override def main(args: Array[String]): Unit = { import unit14.Learn._ val dog = new Dog dog.fly(dog, "飛行技能") } }
import unit14.Learn._ class Dog { val name = "金毛" } class Skill{ def fly(animal: Dog, skill: String) = println(animal.name + "已領悟" + skill) def Q() = println("Q誰誰懷孕") def W() = println("W誰誰懷孕") } object Learn{ implicit def learningType(s : Dog) = new Skill } object Main2 extends App{ override def main(args: Array[String]): Unit = { val dog = new Dog dog.fly(dog, "飛行技能") dog.Q() dog.W() } }
固然了,以上操做也能夠定義在包對象中,即,在object Learn的外面再套一層,package,沒問題的!作用域
在scala2.10後提供了隱式類,可使用implicit聲明類,可是須要注意如下幾點:
—– 其所帶的構造參數有且只能有一個 —– 隱式類必須被定義在「類」或「伴生對象」或「包對象」裏 —– 隱式類不能是case class(case class在定義會自動生成伴生對象與2矛盾) —– 做用域內不能有與之相同名稱的標示符
object StringUtils { implicit class StringImprovement(val s : String){ //隱式類 def increment = s.map(x => (x + 1).toChar) } }
object Main3 extends App{
import unit14.StringUtils._
println("abcd".increment) //bcde }
1) 當方法中的參數的類型與目標類型不一致時
2) 當對象調用所在類中不存在的方法或成員時,編譯器會自動將對象進行隱式轉換
即編譯器是如何查找到缺失信息的,解析具備如下兩種規則:
1) 首先會在當前代碼做用域下查找隱式實體(隱式方法、隱式類、隱式對象)。
2) 若是第一條規則查找隱式實體失敗,會繼續在隱式參數的類型的做用域裏查找。
類型的做用域是指與該類型相關聯的所有伴生模塊,一個隱式實體的類型T它的查找範圍以下:
a) 若是T被定義爲T with A with B with C,那麼A,B,C都是T的部分,在T的隱式解析過程當中,它們的伴生對象都會被搜索。
b) 若是T是參數化類型,那麼類型參數和與類型參數相關聯的部分都算做T的部分,好比 List[String] 的隱式搜索會搜索 List 的伴生對象和 String 的伴生對象。
c) 若是T是一個單例類型 p.T,即T是屬於某個 p 對象內,那麼這個p對象也會被搜索。
d) 若是T是個類型注入 S#T,那麼 S 和 T 都會被搜索。
1) 不能存在二義性
2) 隱式操做不能嵌套