scala基礎之隱式轉換

2021-08-01 23:37:04 字數 4774 閱讀 1496

一 隱式轉換

隱式轉換函式,也被稱作隱式檢視,它是可以把一種型別轉換成另外一種型別,進而可以使用另外一種型別的屬性和方法,從而滿足表示式的要求

語法格式:implicit def 函式名(引數名:引數型別):返回型別 = {}

作用:如果隱式作用域裡存在這個定義,它會隱式地把原始型別的值轉化為增強的型別的值(在需要的時候)

比如現在有兩個沒有關係的類person 和 animal

class

person(val

name:string, val

age:int)

class

animal(val

name:string, val

age:int)

我們知道person有shopping方法,但是animal沒有,怎麼辦呢?

我們就可以在乙個隱式作用域,什麼是隱式作用域

:就是定義隱式函式的地方,可以是乙個類或者

object

或者乙個方法中,注意你不能定義在需要被轉換的類中,然後到其他地方使用這個類,是不會自動轉換的,除非你手動顯示的轉換

class 

join   else  null

}def

join(): unit =

}

object 

implicitclient

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

除非你顯示的轉換

object 

implicitclient

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._

這時候才可以呼叫到目標類的方法

object 

implicitclient

extends

注意點:

# 不能直接將隱式轉換函式放入到源類或者目標類中,那樣是沒有效果的

# 不能將隱式轉換函式放入到目標類,我們還需要在需要的時候靜態匯入目標類

三 隱式轉換規則或者時機

3.1 表示式的型別與預期的不一致

math.sqrt

(fraction(2,4))

sqrt本身是期望傳入乙個double型別,但是你確傳入了乙個fraction物件,那麼就會呼叫fraction的隱式轉換

3.2 當物件訪問乙個不存在的成員時候

就如前面的例子所講,初始化animal,然後呼叫不屬於自己的shopping方法,這時候,就會進行隱式轉換

object 

implicitclient

extends

3.3 當物件呼叫某個方法,該方法存在,但是方法引數不相同

object 

implicitclient

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

/**

*  如果當前作用域沒有查到,他就會到要求的型別的伴生物件查詢

*  當然前提還是必須宣告為

implicit

的val

變數或者函式

*/object

delimters")

}

d1

.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...