Scala提供的隱式轉換和隱式參數功能,是很是有特點的功能。是Java等編程語言所沒有的功能。它能夠容許你手動指定,將某種類型的對象轉換成其餘類型的對象。經過這些功能,能夠實現很是強大,並且特殊的功能。編程
Scala的隱式轉換,其實最核心的就是定義隱式轉換函數,即implicit conversion function。定義的隱式轉換函數,只要在編寫的程序內引入,就會被Scala自動使用。Scala會根據隱式轉換函數的簽名,在程序中使用到隱式轉換函數接收的參數類型定義的對象時,會自動將其傳入隱式轉換函數,轉換爲另一種類型的對象並返回。這就是「隱式轉換」。編程語言
隱式轉換函數叫什麼名字是無所謂的,由於一般不會由用戶手動調用,而是由Scala進行調用。可是若是要使用隱式轉換,則須要對隱式轉換函數進行導入。所以一般建議將隱式轉換函數的名稱命名爲「one2one」的形式。函數
Spark源碼中有大量的隱式轉換和隱式參數,所以必須精通這種語法。spa
1、隱式轉換(案例:特殊售票窗口)對象
2、使用隱式轉換增強現有類型(案例:超人變身)ci
3、隱式轉換函數的做用域與導入作用域
4、隱式轉換的發生時機(案例:特殊售票窗口增強版)get
5、隱式參數(案例:考試簽到)源碼
// 要實現隱式轉換,只要程序可見的範圍內定義隱式轉換函數便可。Scala會自動使用隱式轉換函數。隱式轉換函數與普通函數惟一的語法區別就是,要以implicit開頭,並且最好要定義函數返回類型。it
// 案例:特殊售票窗口(只接受特殊人羣,好比學生、老人等)
class SpecialPerson(val name: String)
class Student(val name: String)
class Older(val name: String)
implicit def object2SpecialPerson (obj: Object): SpecialPerson = {
if (obj.getClass == classOf[Student]) { val stu = obj.asInstanceOf[Student]; new SpecialPerson(stu.name) }
else if (obj.getClass == classOf[Older]) { val older = obj.asInstanceOf[Older]; new SpecialPerson(older.name) }
else Nil
}
var ticketNumber = 0
def buySpecialTicket(p: SpecialPerson) = {
ticketNumber += 1
"T-" + ticketNumber
}
// 隱式轉換很是強大的一個功能,就是能夠在不知不覺中增強現有類型的功能。也就是說,能夠爲某個類定義一個增強版的類,並定義互相之間的隱式轉換,從而讓源類在使用增強版的方法時,由Scala自動進行隱式轉換爲增強類,而後再調用該方法。
// 案例:超人變身
class Man(val name: String)
class Superman(val name: String) {
def emitLaser = println("emit a laster!")
}
implicit def man2superman(man: Man): Superman = new Superman(man.name)
val leo = new Man("leo")
leo.emitLaser
// 1、調用某個函數,可是給函數傳入的參數的類型,與函數定義的接收參數類型不匹配(案例:特殊售票窗口)
// 2、使用某個類型的對象,調用某個方法,而這個方法並不存在於該類型時(案例:超人變身)
// 3、使用某個類型的對象,調用某個方法,雖然該類型有這個方法,可是給方法傳入的參數類型,與方法定義的接收參數的類型不匹配(案例:特殊售票窗口增強版)
// 案例:特殊售票窗口增強版
class TicketHouse {
var ticketNumber = 0
def buySpecialTicket(p: SpecialPerson) = {
ticketNumber += 1
"T-" + ticketNumber
}
}
// 所謂的隱式參數,指的是在函數或者方法中,定義一個用implicit修飾的參數,此時Scala會嘗試找到一個指定類型的,用implicit修飾的對象,即隱式值,並注入參數。
// Scala會在兩個範圍內查找:一種是當前做用域內可見的val或var定義的隱式變量;一種是隱式參數類型的伴生對象內的隱式值
// 案例:考試簽到
class SignPen {
def write(content: String) = println(content)
}
implicit val signPen = new SignPen
def signForExam(name: String) (implicit signPen: SignPen) {
signPen.write(name + " come to exam in time.")
}