天天看點

Scala學習--詳解隐式轉換與隐式參數

Scala提供的隐式轉換和隐式參數是非常有特色的功能,它允許你手動指定,将某種類型的對象轉換成其他類型的對象。

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

隐式轉換函數叫什麼名字是無所謂的,因為通常不會由使用者手動調用,而是由Scala調用,但是如果要使用隐式轉換,則需要對隐式轉換函數進行導入,是以通常建議将隐式轉換函數的名稱命名為”one2one“的形式。

隐式轉換

//隐式轉換函數與普通函數唯一的文法差別就是,要以implicit開頭,而且最好要定義函數傳回類型。

案例:特殊售票視窗(隻接受特殊人群,比如學生,老人等)

class SpecialPerson(val name:Strring)
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
}

調用:
val xiaoming = new Student("xiaoming")
buySpecialTicket(xiaomign)
           

使用隐式轉換加強現有類型

//隐式轉換非常強大的一個功能,就是可以在不知不覺中加強現有類型的功能。也就是說,可以為某個類定義一個加強版的類,并定義互相之間的隐式轉換,進而讓源類在使用加強版的方法時,由Scala自動進行隐式轉換為加強類,然後再調用該方法。

案例:超人變身

class Man(val name:String)
class Superman(val name:String){
	def emitLaser = println("emit a laser")
}

implicit def man2superman(man:Man):Superman = new Superman(man.name)

val xiaoming = new Man("xiaoming")
xiaoming.emitLaser
           

隐式轉換的發生時機

//調用某個函數,但是給函數傳入的參數的類型,與函數定義的接收參數類型不比對,例如案例:特殊的售票視窗

//使用某個類型的對象,調用某個方法,而這個方法并不存在與該類型時(案例:超人變身)

//使用某個類型的對象,調用某個方法,雖然該類型有這個方法,但是給方法傳入的參數類型,與方法定義的接收參數的類型不比對。

隐式參數

//隐式參數,指的是在函數或者方法中,定義一個用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")
}

調用:
signForExam("xiaoming")