10. 隱式轉換
隱式轉換函式是以implicit關鍵字宣告的帶有單個引數的函式。這種函式將會自動應用,將值從一種型別轉換為另一種型別
① 隱式轉換最佳入門案例
首先看下面的程式碼
如果想要轉換成功,就需要藉助隱式轉換函式
為了更好的理解,我們看看反編譯後的位元組碼檔案,底層編譯器是如何隱式轉換函式的
根據需求我們可以將任意資料型別的物件轉換為我們想要的資料型別,以及進行處理
implicit def func2(num: Long): Int = {
(num - 1).toInt
}
val num2: Int = 10L
println(num2) // 9
複製程式碼
② 隱式轉換的細節
-
隱式轉換函式的函式名可以是任意的,隱式轉換與函式名稱無關,只與函式簽名(函式引數型別和返回值型別)有關。
-
隱式函式可以有多個(即:隱式函式列表),但是需要保證在當前環境下,只有一個隱式函式能被識別
③ 強悍的隱式轉換豐富類庫功能
如果需要為一個類增加一個方法,可以通過隱式轉換來實現。(動態增加功能)比如想為 Oracle
類增加一個 delete
方法
看看底層編譯器的魔術
細節
在當前程式中,如果想要給 Oracle
類增加功能是非常簡單的,但是在實際專案中,如果想要增加新的功能就會需要改變原始碼,這是很難接受的。而且違背了軟體開發的 OCP
開發原則
在這種情況下,可以通過隱式轉換函式給類動態新增功能
④ 隱式值
隱式值也叫隱式變數,將某個形參變數標記為implicit,所以編譯器會在方法省略隱式引數的情況下去搜尋作用域內的隱式值作為預設引數
示例程式碼
細節練習
- 以下程式碼的函式命名編譯器如何定義
看看底層編譯器的位元組碼檔案
-
隱式值細節
總結
-
隱式值的優先順序高於預設值
-
當匹配到多個隱式值就會報錯
-
⑤ 隱式類
在 Scala2.10
後提供了隱式類,可以使用 implicit
宣告類,隱式類的非常強大,同樣可以擴充套件類的功能,比前面使用隱式轉換豐富類庫功能更加的方便,在集合中隱式類會發揮重要的作用
示例程式碼
object Main {
def main(args: Array[String]): Unit = {
// 隱式類會獨立生成一個 .class 檔案,還會在當前 Main 類生成一個轉換函式
implicit class Driver(oracle: Oracle) {
def add(): Unit = {
println("Driver add")
}
}
val oracle = new Oracle
// 實質上是呼叫了轉換函式生成一個隱式類物件來呼叫 add 方法
oracle.add() // Driver add
oracle.func() // Oracle func
}
}
class Oracle {
def func(): Unit = {
println("Oracle func")
}
}
複製程式碼
隱式類的特點
-
其所帶的構造引數有且只能有一個
-
隱式類必須被定義在
類
或伴生物件
或包物件
裡,即隱式類不能是 頂級的(top-level objects
) -
隱式類不能是
case class
(型別匹配) -
作用域內不能有與之相同名稱的標示符
⑥ 隱式轉換時機
-
當方法中的引數的型別與目標型別不一致時
-
當物件呼叫所在類中不存在的方法或成員時,編譯器會自動將物件進行隱式轉換(根據型別)
隱式轉換解析規則(瞭解)
隱式轉換前提
-
不能存在二義性
-
隱式操作不能巢狀