類(lèi)型變量界定(Type Variable Bound)翰守、視圖界定(View Bound)孵奶、上下文界定(Context Bound),在scala中算很重要的內(nèi)容了蜡峰,這次博客就來(lái)寫(xiě)點(diǎn)自己的理解了袁。
1、類(lèi)型變量界定(Type Variable Bound):
1. // 編譯錯(cuò)誤
2. def typeVariable[T](a: T, b: T) = {
3. if (a.compareTo(b) > 0) 1
4. else -1
5. }
7. // 通過(guò)編譯
8. def typeVariable[T <: Comparable[T]](a: T, b: T) = {
9. if (a.compareTo(b) > 0) 1
10. else -1
11. }
在上面的例子中湿颅,我們?yōu)榉缎蚑增加了約束载绿,限定上界為Comparable[T],這樣一來(lái)油航,范型類(lèi)型T也就具有了Comparable[T]中的compareTo(T)方法卢鹦,類(lèi)似于java中的繼承。
2劝堪、視圖界定(View Bound):
1. def typeVariable[T <: Comparable[T]](a: T, b: T) = {
2. if (a.compareTo(b) > 0) 1
3. else -1
4. }
這是我們剛剛通過(guò)編譯的代碼冀自,接著我們運(yùn)行一下:
1. val v1 = typeVariable("scala", "java")
2. println(v1) // scala
運(yùn)行結(jié)果為:scala,但是秒啦,如果我們輸入數(shù)字的話(huà)熬粗,便會(huì)報(bào)錯(cuò):
1. val v2 = typeVariable(100, 200)
2. println(v2)
3. Error:(15, 12) inferred type arguments [Int] do not conform to method typeVariable's type parameter bounds [T <: Comparable[T]]
4. val v2 = typeVariable(100, 200)
5. ^
因?yàn)槲覀兊腎nt類(lèi)型并沒(méi)有遵循我們的范型約束。如果我們此時(shí)想成功運(yùn)行的話(huà)余境,就需要進(jìn)行一次隱式轉(zhuǎn)換驻呐,將Int類(lèi)型轉(zhuǎn)換成支持Comparable[T]的類(lèi)型灌诅,那么,我們的視圖界定便能出場(chǎng)了:
1. def typeVariable[T <% Comparable[T]](a: T, b: T) = {
2. if (a.compareTo(b) > 0) a
3. else b
4. }
5. val v2 = typeVariable(100, 200)
6. println(v2) // 200
從代碼中發(fā)現(xiàn)含末,范型限定時(shí)猜拾,我們將"<:"改為了"<%",這樣佣盒,原本的類(lèi)型變量界定就轉(zhuǎn)換成了視圖界定挎袜,而視圖界定幫我們進(jìn)行了隱式轉(zhuǎn)換,將Int轉(zhuǎn)換成了支持Comparable[T]的RichInt類(lèi)型肥惭。
<u style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; overflow-wrap: break-word;">編寫(xiě)代碼時(shí)盯仪,"<%"的限定較為寬松,不僅繼承了Comparable[T]的類(lèi)能夠順利運(yùn)行蜜葱,而且通過(guò)隱式轉(zhuǎn)換而來(lái)的繼承Comparable[T]的類(lèi)也能夠順利運(yùn)行</u>全景。
3、上界(Upper Bound)牵囤、下界(Lower Bound):
有上界爸黄,那么也有下界,上界我們用"<:"來(lái)表示揭鳞,例如:A <: B馆纳,表示B為A的上界,在java中即A繼承B汹桦。
下界用">:"來(lái)表示鲁驶,例如A >: B,表示B為A的下界舞骆,此時(shí)B繼承A钥弯。
4、上下文界定(Context Bound):
上下文界定的類(lèi)型參數(shù)形式為T(mén):M的形式督禽,其中M是一個(gè)泛型類(lèi)脆霎,這種形式要求存在一個(gè)M[T]類(lèi)型的隱式值:
1. class Person(val age: Int) {
2. println("person==> " + age)
3. }
5. // PersonOrdering繼承了Ordering[T],而Ordering[T]又繼承了Comporator[T]狈惫,所以下面方法中有compare(x: T, y: T)方法
6. class PersonOrdering extends Ordering[Person] {
7. override def compare(x: Person, y: Person): Int = {
8. if (x.age > y.age) 1 else -1
9. }
10. }
12. // 該類(lèi)定義了一個(gè)上下文界定睛蛛,意思是
13. // 在其作用域內(nèi),必須有一個(gè)Ordering[T]的隱式值胧谈,而這個(gè)隱式值可以作用于內(nèi)部的方法
14. class Pair[T: Ordering](val first: T, val second: T) {
15. // 該方法需要一個(gè)類(lèi)型為Ordering[T]的隱式參數(shù)
16. def old(implicit ord: Ordering[T]) = {
17. if (ord.compare(first, second) > 0) first else second
18. }
19. }
21. // 定義一個(gè)隱式值忆肾,類(lèi)型為Ordering[T]
22. implicit val po = new PersonOrdering
23. val p = new Pair(new Person(18), new Person(19))
24. // 調(diào)用old方法時(shí),不需要傳入?yún)?shù)菱肖,根據(jù)我們的上下文界定要求客冈,po滿(mǎn)足要求,因此作為參數(shù)傳入old
25. println(p.old.age) // 19
這次的博客雖然是說(shuō)界定稳强,但是也扯到了不少的隱式轉(zhuǎn)換场仲,所以需要對(duì)scala有一些基本的了解和悦,另外文章中如果有出錯(cuò)的地方,歡迎指正渠缕。