Spark基礎-scala學習(八、隱式轉換與隱式參數)


大綱

  1. 隱式轉換
  2. 使用隱式轉換加強現有類型
  3. 導入隱式轉換函數
  4. 隱式轉換的發生時機
  5. 隱式參數

隱式轉換

  1. 要實現隱式轉換,只要程序可見的范圍內定義隱式轉換函數即可。Scala會自動使用隱式轉換函數。隱式轉換函數與普通函數唯一的語法區別就是,要以implicit開頭,而且一定要定義函數返回類型
  2. 案例:特殊售票窗口(只接受特殊人群,比如學生、老人等)
scala> :paste
// Entering paste mode (ctrl-D to finish)

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
}

// Exiting paste mode, now interpreting.

<pastie>:15: warning: implicit conversion method object2SpecialPerson should be enabled
by making the implicit value scala.language.implicitConversions visible.
This can be achieved by adding the import clause 'import scala.language.implicitConversions'
or by setting the compiler option -language:implicitConversions.
See the Scaladoc for value scala.language.implicitConversions for a discussion
why the feature should be explicitly enabled.
implicit def object2SpecialPerson(obj:Object):SpecialPerson = {
             ^
defined class SpecialPerson
defined class Student
defined class Older
object2SpecialPerson: (obj: Object)SpecialPerson
ticketNumber: Int = 0
buySpecialTicket: (p: SpecialPerson)String

scala> val s = new Student("leo")
s: Student = Student@4d266391

scala> buySpecialTicket(s)
res0: String = T-1

scala> val o = new Older("Jike")
o: Older = Older@6afbe6a1

scala> buySpecialTicket(o)
res1: String = T-2

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

  1. 隱式轉換可以在不知不覺中加強現有類型的功能。也就是說,可以為某個類定義一個加強版的類,並定義互相之間的隱式轉換,從而讓源類在使用加強版的方法時,由scala自動進行隱式轉換為加強類,然后再調用該方法
  2. 案例:超人變身
scala> :paste
// Entering paste mode (ctrl-D to finish)

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)


// Exiting paste mode, now interpreting.

defined class Man
defined class Superman
man2superman: (man: Man)Superman

scala> val leo = new Man("leo")
leo: Man = Man@618e7761

scala> leo.emitLaser
emit a laster!

隱式轉換函數的作用域與導入

  1. scala會使用兩種隱式轉換,一種是源類型,或者目標類型的伴生對象內的隱式轉換函數;一種是當前程序作用域內的可以用唯一標識符表示的隱式轉換函數
  2. 如果隱式轉換函數不在上述兩種情況下的話,那么就必須手動使用import語法引入某個包下的隱式轉換函數,比如import test._ 通常建議,僅僅在需要進行隱式轉換的地方,比如某個函數或者方法內,用import導入隱式轉換函數,這樣可以縮小隱式轉換函數的作用域,避免不需要的隱式轉換。

隱式轉換的發生時機

  1. 調用某個函數,但是給函數傳入的參數的類型,與函數定義的接收參數類型不匹配(案例:特殊售票窗口)
  2. 使用某個類型的對象,調用某個方法,而這個方法並不在於該類型時(案例:超人變身)
  3. 使用某個類型的對象,調用某個方法,雖然該類型有這個方法,但是給方法傳入的參數類型,與方法定義的接收參數的類型不匹配(案例:特殊售票窗口加強版)
  4. 案例:特殊售票窗口加強版
scala> :paste
// Entering paste mode (ctrl-D to finish)

class TicketHouse {
 var ticketNumber= 0
 def buySpecialTicket(p:SpecialPerson) = {
  ticketNumber += 1
  "T-"+ticketNumber
 }
}

// Exiting paste mode, now interpreting.

defined class TicketHouse

scala> val leo = new Student("leo")
leo: Student = Student@217dc48e

scala> val ticket = new TicketHouse
ticket: TicketHouse = TicketHouse@7a5a26b7

scala> ticket.buySpecialTicket(leo)
res1: String = T-1

隱式參數

  1. 所謂的隱式參數,指的是在函數或者方法中,定義一個用implicit修飾的參數,此時Scala會嘗試找到一個指定類型的,用implicit修飾的對象,即隱式值,並注入參數
  2. Scala會在兩個范圍內查找:一種是當前作用域內可見的val或var定義的隱式變量;一種是隱式參數類型的伴生對象內的隱式值
  3. 案例:考試簽到
scala> :paste
// Entering paste mode (ctrl-D to finish)

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.")
}

// Exiting paste mode, now interpreting.

defined class SignPen
signPen: SignPen = SignPen@6c4d0224
signForExam: (name: String)(implicit signPen: SignPen)Unit

scala> signForExam("leo")(signPen)
leo come to exam in time.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM