日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Scala Implicit

發布時間:2025/4/5 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Scala Implicit 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

序:前段時間用spray的時候對于http請求的參數以及response的結果用json格式的時候遇到了一個隱式轉換,又專門查了一下加深下印象。溫故知新果然又有收獲,要記住這一句:隱式轉換函數只在意 輸入類型,返回類型。

我們經常在scala 源碼里上看到類似implicit這個關鍵字。

一開始不太理解,后來看了看,發現implicit這個隱式轉換是支撐scala的易用、容錯以及靈活語法的基礎。

我們經常使用的一些集合方法里面就用到了implicit,比如:

def flatMap[S, That](f: T => GenTraversableOnce[S])(implicit bf: CanBuildFrom[Repr, S, That]): That = if (bf(repr).isCombiner) { ...... }

?

1. 隱式轉換函數的定義:

我們在scala repl里定義一個方法foo,接受一個string的參數,打印出message

?當我們傳入字符串參數"2"的時候,輸出2

?但是當傳入的類型是int而不是string的時候,出現類型不匹配異常。

?如果我們想支持隱式轉換,將int轉化為string,可以定義一個隱式函數,def implicit intToString( i : Int) = i.toString

?這里注意一下這個隱式函數的輸入參數和返回值。

?輸入參數:接受隱式轉換入參為int類型

?返回值: 返回結果是string.

scala> def foo(msg : String) = println(msg) foo: (msg: String)Unit scala> foo("2") 2 scala> foo(3) <console>:9: error: type mismatch; found : Int(3) required: String foo(3) ^ scala> implicit def intToString(i:Int) = i.toString warning: there were 1 feature warning(s); re-run with -feature for details intToString: (i: Int)String scala> foo(3) 3 scala> def bar(msg : String) = println("aslo can use implicit function intToString...result is "+msg) bar: (msg: String)Unit scala> bar(33) aslo can use implicit function intToString...result is 33

總結一下,我的理解是:隱式函數是在一個scop下面,給定一種輸入參數類型,自動轉換為返回值類型的函數,和函數名,參數名無關。

這里intToString隱式函數是作用于一個scop的,這個scop在當前是一個scala repl,超出這個作用域,將不會起到隱式轉換的效果。

為什么我會這么定義隱式函數,下面我再定義一個相同的輸入類型為int,和返回值類型為string的隱式函數名為int2str:

scala> implicit def int2str(o :Int) = o.toString warning: there were 1 feature warning(s); re-run with -feature for details int2str: (o: Int)String scala> bar(33) <console>:13: error: type mismatch; found : Int(33) required: String Note that implicit conversions are not applicable because they are ambiguous: both method intToString of type (i: Int)String and method int2str of type (o: Int)String are possible conversion functions from Int(33) to String bar(33) ^


跑出了二義性的異常,說的是intToString和int2str這2個隱式函數都是可以處理bar(33)的,編譯器不知道選擇哪個了。證明了隱式函數和函數名,參數名無關,只和輸入參數與返回值有關。

2. 隱式函數的應用

我們可以隨便的打開scala函數的一些內置定義,比如我們最常用的map函數中->符號,看起來很像php等語言。

但實際上->確實是一個ArrowAssoc類的方法,它位于scala源碼中的Predef.scala中。下面是這個類的定義:

final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal { // `__leftOfArrow` must be a public val to allow inlining. The val // used to be called `x`, but now goes by `__leftOfArrow`, as that // reduces the chances of a user's writing `foo.__leftOfArrow` and // being confused why they get an ambiguous implicit conversion // error. (`foo.x` used to produce this error since both // any2Ensuring and any2ArrowAssoc pimped an `x` onto everything) @deprecated("Use `__leftOfArrow` instead", "2.10.0") def x = __leftOfArrow @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) def →[B](y: B): Tuple2[A, B] = ->(y) } @inline implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)


我們看到def ->[B] (y :B)返回的其實是一個Tuple2[A,B]類型。

我們定義一個Map:

scala> val mp = Map(1->"game1",2->"game_2") mp: scala.collection.immutable.Map[Int,String] = Map(1 -> game1, 2 -> game_2)


這里 1->"game1"其實是1.->("game_1")的簡寫。理解這個原理之后,以前這么寫Map的時候這個箭頭的問題總是寫錯,這下再也不會寫錯了。

這里怎么能讓整數類型1能有->方法呢。

這里其實any2ArrowAssoc隱式函數起作用了,這里接受的參數[A]是泛型的,所以int也不例外。

調用的是:將整型的1 implicit轉換為 ArrowAssoc(1)

看下構造方法,將1當作__leftOfArrow傳入。

->方法的真正實現是生產一個Tuple2類型的對象(__leftOfArrow,y ) 等價于(1, "game_id")

這就是一個典型的隱式轉換應用。

?

其它還有很多類似的隱式轉換,都在Predef.scala中:

例如:Int,Long,Double都是AnyVal的子類,這三個類型之間沒有繼承的關系,不能直接相互轉換。

在Java里,我們聲明Long的時候要在末尾加上一個L,來聲明它是long。

但在scala里,我們不需要考慮那么多,只需要:

scala> val l:Long = 10 l: Long = 10


這就是implicit函數做到的,這也是scala類型推斷的一部分,靈活,簡潔。

其實這里調用是:

val l : Long = int2long(10)

最后的總結:

1. 記住隱式轉換函數的同一個scop中不能存在參數和返回值完全相同的2個implicit函數。

2. 隱式轉換函數只在意 輸入類型,返回類型。

3. 隱式轉換是scala的語法靈活和簡潔的重要組成部分。

轉載于:https://my.oschina.net/u/779531/blog/904624

總結

以上是生活随笔為你收集整理的Scala Implicit的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。