一 隱式轉換
隱式轉換函式,也被稱作隱式檢視,它是可以把一種型別轉換成另外一種型別,進而可以使用另外一種型別的屬性和方法,從而滿足表示式的要求
語法格式:implicit def 函式名(引數名:引數型別):返回型別 = {}
作用:如果隱式作用域裡存在這個定義,它會隱式地把原始型別的值轉化為增強的型別的值(在需要的時候)
比如現在有兩個沒有關係的類person 和 animal
class
person(val
name:string, val
age:int)
class
animal(val
name:string, val
age:int)
我們知道person有shopping方法,但是animal沒有,怎麼辦呢?
我們就可以在乙個隱式作用域,什麼是隱式作用域
:就是定義隱式函式的地方,可以是乙個類或者
object
或者乙個方法中,注意你不能定義在需要被轉換的類中,然後到其他地方使用這個類,是不會自動轉換的,除非你手動顯示的轉換
classjoin else null
}def
join(): unit =
}
objectimplicitclient
extends
else null
}val p1
= new
person("nicky",29)
val p2
= new
person("baobao",27)
val dog
= new
animal("dog",4)
val cat
= new
animal("cat",5)
dog.shopping(cat
) dog
.shopping(p2
)}
如果你是定義在被轉換的類裡面:
class但是又在其他地放建立該物件,那麼隱式函式是不會生效的。animal(val
name:string, val
age:int) else null
}}
object除非你顯示的轉換implicitclient
extends
objectimplicitclient
extends
二 隱式轉換函式的作用域和匯入
在scala中,隱式解析一般分為兩個階段:
2.1:隱式轉換的作用域中查詢
首先在隱式轉換的作用域中查詢,隱式轉換的作用域已經介紹了。就是在定義隱式函式的作用域中,可以是方法或者類或者object中。
2.2:到相應的源或者目標類的伴生物件中查詢
其次如果隱式作用域沒有找到,那麼編譯器就會自動到相應的源或者目標類的伴生物件中查詢 源類
2目標類:即源類希望被轉換城目標類,從而呼叫目標類的方法
第一種情況:去源類的伴生類中查詢
class這時候發現,可以初始化完畢源類之後,源類轉化成目標類,就可以呼叫目標類的方法了animal(val
name:string, val
age:int)
object
animal else null
}}
第二種情況:到目標類的伴生物件中查詢,也就需要轉換成的那個型別的伴生物件
class這時候發現,可以初始化完畢源類之後,源類轉化成目標類,仍然不可以呼叫目標類的方法了。怎麼回事了?因為這樣是不夠的,你還需要在初始化的時候顯示靜態匯入目標類,什麼是靜態匯入,就是匯入類中的所有成員:person(val
name:string, val
age:int)
object
person else null
}}
import com.scala.implicits.person._
這時候才可以呼叫到目標類的方法
objectimplicitclient
extends
注意點:
# 不能直接將隱式轉換函式放入到源類或者目標類中,那樣是沒有效果的
# 不能將隱式轉換函式放入到目標類,我們還需要在需要的時候靜態匯入目標類
三 隱式轉換規則或者時機
3.1 表示式的型別與預期的不一致
math.sqrtsqrt本身是期望傳入乙個double型別,但是你確傳入了乙個fraction物件,那麼就會呼叫fraction的隱式轉換(fraction(2,4))
3.2 當物件訪問乙個不存在的成員時候
就如前面的例子所講,初始化animal,然後呼叫不屬於自己的shopping方法,這時候,就會進行隱式轉換
object3.3 當物件呼叫某個方法,該方法存在,但是方法引數不相同implicitclient
extends
objectimplicitclient
extends
四 隱式引數
在普通的函式或者方法中,可以帶有乙個隱式的引數列表:
注意:# 如果程式顯示提供,雖然隱式的,但是不會去隱式作用域查詢,因為已經提供了引數
# 如果沒有顯示提供,那麼首先會在隱式作用域查詢 implicit 修飾val 或者 函式,val是該型別的變數,函式是返回該型別的函式
# 如果隱式作用域沒有,則去隱式引數型別相對應的伴生物件中查詢implicit 修飾的val 或者函式,val是該引數型別的變數,函式是返回該型別的函式
首先定乙個帶有隱式引數的函式:
case class
delimters(left:string,right:string)
/*建立
delimiters例項,
並賦給乙個變數
*/val d1
= delimters
("left","right")
/**
編譯會報錯
error:(9, 12)could not find implicit value for parameter
* delims:com.scala.implicits.delimters
* d1.quote("-what-")*/
原因在於,你既沒有顯示提供該值,又沒在隱式作用域或者該引數型別的伴生物件中查詢到該隱式值
顯示提供該引數 /*
它既然提示找不到隱式值,那我們給他乙個顯示的
delims*/
val d2
= delimters
("<",">")
/*這樣是肯定沒有問題的,結果:
,但是這樣就根本就沒有用到隱式引數
*/d1
.quote("what")(d2
) //
柯里化
/*** 隱式引數的作用就是,如果沒有提供該值,那麼就會自動從隱式作用域去查詢該引數值
* 現在我們討論隱式引數是如何查詢的*/
/**
首先在當前作用域,需要提供乙個隱式引數的變數或者函式
* 該變數或者函式必須有
implicit
關鍵字修飾,否則查不到
* 但是不能同時提供
2個,只能提供乙個,否則報錯
*/implicit val d3
= delimters
("<",">")
/*我們並沒有提供
delimters
的引數,但是它查到了
d3,結果
*/d1
.quote("username")
implicit def delims = delimters
("[","]")
/*我們並沒有提供
delimters
的引數,但是它查到了
delims函式,
結果[address]*/
d1.quote("address")
/**d1* 如果當前作用域沒有查到,他就會到要求的型別的伴生物件查詢
* 當然前提還是必須宣告為
implicit
的val
變數或者函式
*/object
delimters")
}
.quote("connection")
object
delimters d1
.quote("connection")
五 利用隱式引數進行隱式轉換
我們先看乙個場景:
def
small[t](a:t,b:t):t =
由於t 我們並不知道他是否可以應用比較符,所以這段**編譯是有問題的。
那我們可以提供乙個轉換函式:
def
small[t](a:t,b:t)(implicit
order:t => ordered[t]):t =
由於ordered[t]trait可以接收乙個型別為t作為引數的比較操作,所以編譯是沒有問題的
Scala之隱式轉換
隱式轉換函式是以implicit關鍵字宣告帶有單個引數的函式。這種函式將會自動應用 package top.mgy object implicitdome def main args array string unit 上面的將double轉為int的函式f1將會自動應用的作用域中所有需要將doub...
Scala 基礎7 隱式轉換
scala編譯器在編譯的時候如果發現型別不匹配,那麼就會使用隱式轉換來嘗試將當前型別轉換為預期的型別 在變數 方法或者類的前邊用implicit修飾,就表示這是乙個隱式轉換規則。需要注意的是,隱式轉換是按照規則轉換的,也就是說和名字無關。編譯器在同乙個地方只會新增一次隱式操作,不會在新增乙個隱式操作...
Scala隱式轉換之隱式引數 1
函式或者方法可以帶有乙個標記為implicit的引數。在這種情況下,編譯器將會查詢預設值,提供給該函式或者方法。示例 case class d left string,right string def quote title string implicit d d d.left title d.ri...