Java Scala的隱式轉(zhuǎn)換詳解
隱式轉(zhuǎn)換是在Scala編譯器進(jìn)行類(lèi)型匹配時(shí),如果找不到合適的類(lèi)型,那么隱式轉(zhuǎn)換會(huì)讓編譯器在作用范圍內(nèi)自動(dòng)推導(dǎo)出來(lái)合適的類(lèi)型。
一、隱式值與隱式參數(shù)
隱式值是指在定義參數(shù)時(shí)前面加上implicit。隱式參數(shù)是指在定義方法時(shí),方法中的部分參數(shù)是由implicit修飾【必須使用柯里化的方式,將隱式參數(shù)寫(xiě)在后面的括號(hào)中】。隱式轉(zhuǎn)換作用就是:當(dāng)調(diào)用方法時(shí),不必手動(dòng)傳入方法中的隱式參數(shù),Scala會(huì)自動(dòng)在作用域范圍內(nèi)尋找隱式值自動(dòng)傳入。
隱式值和隱式參數(shù)需要注意以下幾點(diǎn):
1.同類(lèi)型的參數(shù)的隱式值只能在作用域內(nèi)出現(xiàn)一次,同一個(gè)作用域內(nèi)不能定義多個(gè)類(lèi)型一樣的隱式值。2.implicit關(guān)鍵字必須放在隱式參數(shù)定義的開(kāi)頭
3.一個(gè)方法只有一個(gè)參數(shù)是隱式轉(zhuǎn)換參數(shù)時(shí),那么可以直接定義implicit關(guān)鍵字修飾的參數(shù),調(diào)用時(shí)直接創(chuàng)建類(lèi)型不傳入?yún)?shù)即可。
4.一個(gè)方法如果有多個(gè)參數(shù),要實(shí)現(xiàn)部分參數(shù)的隱式轉(zhuǎn)換,必須使用柯里化這種方式,隱式關(guān)鍵字出現(xiàn)在后面,只能出現(xiàn)一次
package com.bjsxt.scala object ImplicitValue { /** * 隱式值和隱式參數(shù)需要注意以下幾點(diǎn): * 1.同類(lèi)型的參數(shù)的隱式值只能在作用域內(nèi)出現(xiàn)一次,同一個(gè)作用域內(nèi)不能定義多個(gè)類(lèi)型一樣的隱式值。 * 2.implicit關(guān)鍵字必須放在隱式參數(shù)定義的開(kāi)頭 * 3.一個(gè)方法只有一個(gè)參數(shù)是隱式轉(zhuǎn)換參數(shù)時(shí),那么可以直接定義implicit關(guān)鍵字修飾的參數(shù),調(diào)用時(shí)直接創(chuàng)建類(lèi)型不傳入?yún)?shù)即可。 * 4.一個(gè)方法如果有多個(gè)參數(shù),要實(shí)現(xiàn)部分參數(shù)的隱式轉(zhuǎn)換,必須使用柯里化這種方式,隱式關(guān)鍵字出現(xiàn)在后面,只能出現(xiàn)一次 */ // * 4.一個(gè)方法如果有多個(gè)參數(shù),要實(shí)現(xiàn)部分參數(shù)的隱式轉(zhuǎn)換, // 必須使用柯里化這種方式,隱式關(guān)鍵字出現(xiàn)在后面,只能出現(xiàn)一次 def Student(age:Int)(implicit name:String,i:Int) = { println(s"student = $name,age = $age,score = $i") } // * 3.一個(gè)方法只有一個(gè)參數(shù)是隱式轉(zhuǎn)換參數(shù)時(shí),那么可以直接定義implicit關(guān)鍵字修飾的參數(shù), // 調(diào)用時(shí)直接創(chuàng)建類(lèi)型不傳入?yún)?shù)即可。 def Teacher(implicit name:String) = { println(s"teacher name is =$name") } def main(args: Array[String]): Unit = { // * 1.同類(lèi)型的參數(shù)的隱式值只能在作用域內(nèi)出現(xiàn)一次, // 同一個(gè)作用域內(nèi)不能定義多個(gè)類(lèi)型一樣的隱式值。比如這里的String、Int類(lèi)型,各自只能定義一個(gè) implicit val name:String = "zhangsan" implicit val i:Int = 100 //這里使用了隱式參數(shù),只用傳入age那個(gè)參數(shù),后面兩個(gè)參數(shù)可以不填,默認(rèn)使用隱式值 Student(100) //這里是直接使用了隱式值,可以不填參數(shù),當(dāng)然也可以給定參數(shù),給定參數(shù)的話(huà)就是取給的參數(shù)的值 Teacher } }
輸出的結(jié)果:會(huì)自動(dòng)尋找對(duì)應(yīng)的函數(shù),并且進(jìn)行隱式轉(zhuǎn)換。
student = zhangsan,age = 100,score = 100 teacher name is =zhangsan
二、隱式轉(zhuǎn)換函數(shù)
隱式轉(zhuǎn)換函數(shù)是使用關(guān)鍵字implicit修飾的方法。當(dāng)Scala運(yùn)行時(shí),假設(shè)如果A類(lèi)型變量調(diào)用了method()這個(gè)方法,發(fā)現(xiàn)A類(lèi)型的變量沒(méi)有method()方法,而B(niǎo)類(lèi)型有此method()方法,會(huì)在作用域中尋找有沒(méi)有隱式轉(zhuǎn)換函數(shù)將A類(lèi)型轉(zhuǎn)換成B類(lèi)型,如果有隱式轉(zhuǎn)換函數(shù),那么A類(lèi)型就可以調(diào)用method()這個(gè)方法。
隱式轉(zhuǎn)換函數(shù)注意:隱式轉(zhuǎn)換函數(shù)只與函數(shù)的參數(shù)類(lèi)型和返回類(lèi)型有關(guān),與函數(shù)名稱(chēng)無(wú)關(guān),所以作用域內(nèi)不能有相同的參數(shù)類(lèi)型和返回類(lèi)型的不同名稱(chēng)隱式轉(zhuǎn)換函數(shù)。
package com.bjsxt.scala class Animal(name:String){ def canFly()= { println(s"$name can fly....") } } class Rabbit(xname:String){ val name = xname } object ImplicitValue2 { //定義隱式轉(zhuǎn)換函數(shù) implicit def RabbitToAnimal(r:Rabbit):Animal = { new Animal(r.name) } //注意隱式轉(zhuǎn)換函數(shù)只與參數(shù)類(lèi)型和返回值類(lèi)型有關(guān), // 與函數(shù)名無(wú)關(guān),所以不能定義兩個(gè)相同類(lèi)型的函數(shù),雖然函數(shù)名不同,下面這個(gè)就是非法的 // implicit def Rabbit(r:Rabbit):Animal = { // new Animal(r.name) // } def main(args: Array[String]): Unit = { val rabbit = new Rabbit("rabbit") //這里rabbit調(diào)用不了canFly,因?yàn)镽abbit類(lèi)中沒(méi)有canFly方法, // 但定義了隱式轉(zhuǎn)換函數(shù),那就會(huì)往Animal類(lèi)中找 rabbit.canFly() } }
運(yùn)行結(jié)果:
rabbit can fly....
三、隱式類(lèi)
使用implicit關(guān)鍵字修飾的類(lèi)就是隱式類(lèi)。若一個(gè)變量A沒(méi)有某些方法或者某些變量時(shí),而這個(gè)變量A可以調(diào)用某些方法或者某些變量時(shí),可以定義一個(gè)隱式類(lèi),隱式類(lèi)中定義這些方法或者變量,隱式類(lèi)中傳入A即可。
隱式類(lèi)注意:
1.隱式類(lèi)必須定義在類(lèi),包對(duì)象,伴生對(duì)象中
2.隱式類(lèi)的構(gòu)造必須只有一個(gè)參數(shù),同一個(gè)類(lèi),包對(duì)象,伴生對(duì)象中不能出現(xiàn)同類(lèi)型構(gòu)造的隱式類(lèi)。
package com.bjsxt.scala //隱式類(lèi) class Rabbit1(xname:String){ val name = xname } object ImplicitValue3 { //定義隱式類(lèi),只能在object中定義,并且只能傳入一個(gè)參數(shù) //不能出現(xiàn)同類(lèi)型構(gòu)造的隱式類(lèi)。(同類(lèi)型:參數(shù)類(lèi)型和返回值類(lèi)型,與類(lèi)名無(wú)關(guān)) implicit class Animal1(r:Rabbit1){ def showName() = { println(s"${r.name} is Rabbit....")//對(duì)象.屬性需要加“{}” } } def main(args: Array[String]): Unit = { val rabbit = new Rabbit1("RABBIT") // Rabbit1類(lèi)中沒(méi)有showName方法,這是會(huì)找隱式類(lèi) rabbit.showName() } }
運(yùn)行結(jié)果:
RABBIT is Rabbit....
到此這篇關(guān)于Java Scala的隱式轉(zhuǎn)換詳解的文章就介紹到這了,更多相關(guān)Scala隱式轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot構(gòu)建優(yōu)雅的RESTful接口過(guò)程詳解
這篇文章主要介紹了spring boot構(gòu)建優(yōu)雅的RESTful接口過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Spring 使用JavaConfig實(shí)現(xiàn)配置的方法步驟
這篇文章主要介紹了Spring 使用JavaConfig實(shí)現(xiàn)配置的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01springboot實(shí)現(xiàn)yml里的自定義配置方法
這篇文章主要介紹了springboot實(shí)現(xiàn)yml里的自定義配置方法,主要介紹三種,字符串配置,數(shù)組配置和帶默認(rèn)值的配置,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Java預(yù)覽PDF時(shí)的文件名稱(chēng)問(wèn)題及解決
這篇文章主要介紹了Java預(yù)覽PDF時(shí)的文件名稱(chēng)問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01SpringMVC通過(guò)RESTful結(jié)構(gòu)實(shí)現(xiàn)頁(yè)面數(shù)據(jù)交互
RESTFUL是一種網(wǎng)絡(luò)應(yīng)用程序的設(shè)計(jì)風(fēng)格和開(kāi)發(fā)方式,基于HTTP,可以使用XML格式定義或JSON格式定義。RESTFUL適用于移動(dòng)互聯(lián)網(wǎng)廠(chǎng)商作為業(yè)務(wù)接口的場(chǎng)景,實(shí)現(xiàn)第三方OTT調(diào)用移動(dòng)網(wǎng)絡(luò)資源的功能,動(dòng)作類(lèi)型為新增、變更、刪除所調(diào)用資源2022-08-08Spring @Cacheable redis異常不影響正常業(yè)務(wù)方案
這篇文章主要介紹了Spring @Cacheable redis異常不影響正常業(yè)務(wù)方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02mybatis中使用not?in與?in的寫(xiě)法說(shuō)明
這篇文章主要介紹了mybatis中使用not?in與?in的寫(xiě)法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01