站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        Scala 使用 Option、Some、None,避免使用 Null


        避免 null 使用

        大多數(shù)語言都有一個(gè)特殊的關(guān)鍵字或者對象來表示一個(gè)對象引用的是”無”,在 Java,它是 null。在 Java 里,null 是一個(gè)關(guān)鍵字,不是一個(gè)對象,所以對它調(diào)用任何方法都是非法的。但是這對語言設(shè)計(jì)者來說是一件令人疑惑的選擇。為什么要在程序員希望返回一個(gè)對象的時(shí)候返回一個(gè)關(guān)鍵字呢?

        Scala 的 Option類型

        為了讓所有東西都是對象的目標(biāo)更加一致,也為了遵循函數(shù)式編程的習(xí)慣,Scala 鼓勵(lì)你在變量和函數(shù)返回值可能不會引用任何值的時(shí)候使用 Option 類型。在沒有值的時(shí)候,使用 None,這是 Option 的一個(gè)子類。如果有值可以引用,就使用 Some 來包含這個(gè)值。Some 也是 Option 的子類。 None 被聲明為一個(gè)對象,而不是一個(gè)類,因?yàn)槲覀冎恍枰囊粋€(gè)實(shí)例。這樣,它多少有點(diǎn)像 null 關(guān)鍵字,但它卻是一個(gè)實(shí)實(shí)在在的,有方法的對象。

        應(yīng)用例子

        Option 類型的值通常作為 Scala 集合類型(List, Map 等)操作的返回類型。比如 Map 的 get 方法:

        scala> val capitals = Map("France"->"Paris", "Japan"->"Tokyo", "China"->"Beijing")  capitals: scala.collection.immutable.Map[String,String] = Map(France -> Paris, Japan -> Tokyo, China -> Beijing)    scala> capitals get "France"  res0: Option[String] = Some(Paris)    scala> capitals get "North Pole"  res1: Option[String] = None

        Option 有兩個(gè)子類別,Some 和 None。當(dāng)程序回傳 Some 的時(shí)候,代表這個(gè)函式成功地給了你一個(gè) String,而你可以透過 get() 函數(shù)拿到那個(gè) String,如果程序返回的是 None,則代表沒有字符串可以給你。

        在返回 None,也就是沒有 String 給你的時(shí)候,如果你還硬要調(diào)用 get() 來取得 String 的話,Scala 一樣是會拋出一個(gè) NoSuchElementException 異常給你的。 我們也可以選用另外一個(gè)方法 getOrElse。這個(gè)方法在這個(gè) Option 是 Some 的實(shí)例時(shí)返回對應(yīng)的值,而在是 None 的實(shí)例時(shí)返回傳入的參數(shù)。換句話說,傳入 getOrElse 的參數(shù)實(shí)際上是默認(rèn)返回值。

        scala> capitals get "North Pole" get  warning: there was one feature warning; re-run with -feature for details  java.util.NoSuchElementException: None.get    at scala.None$.get(Option.scala:347)    at scala.None$.get(Option.scala:345)    ... 33 elided    scala> capitals get "France" get  warning: there was one feature warning; re-run with -feature for details  res3: String = Paris    scala> (capitals get "North Pole") getOrElse "Oops"  res7: String = Oops    scala> capitals get "France" getOrElse "Oops"  res8: String = Paris

        通過模式匹配分離可選值,如果匹配的值是 Some 的話,將 Some 里的值抽出賦給 x 變量:

        def showCapital(x: Option[String]) = x match {      case Some(s) => s      case None => "?"  }

        提示

        Scala 程序使用 Option 非常頻繁,在 Java 中使用 null 來表示空值,代碼中很多地方都要添加 null 關(guān)鍵字檢測,不然很容易出現(xiàn) NullPointException。因此 Java 程序需要關(guān)心那些變量可能是 null,而這些變量出現(xiàn) null 的可能性很低,但一但出現(xiàn),很難查出為什么出現(xiàn) NullPointerException。 Scala 的 Option 類型可以避免這種情況,因此 Scala 應(yīng)用推薦使用 Option 類型來代表一些可選值。使用 Option 類型,讀者一眼就可以看出這種類型的值可能為 None。

        實(shí)際上,多虧 Scala 的靜態(tài)類型,你并不能錯(cuò)誤地嘗試在一個(gè)可能為 null 的值上調(diào)用方法。雖然在 Java 中這是個(gè)很容易犯的錯(cuò)誤,它在 Scala 卻通不過編譯,這是因?yàn)?Java 中沒有檢查變量是否為 null 的編程作為變成 Scala 中的類型錯(cuò)誤(不能將 Option[String] 當(dāng)做 String 來使用)。所以,Option 的使用極強(qiáng)地鼓勵(lì)了更加彈性的編程習(xí)慣。

        詳解 Option[T]

        在 Scala 里 Option[T] 實(shí)際上是一個(gè)容器,就像數(shù)組或是 List 一樣,你可以把他看成是一個(gè)可能有零到一個(gè)元素的 List。

        當(dāng)你的 Option 里面有東西的時(shí)候,這個(gè) List 的長度是 1(也就是 Some),而當(dāng)你的 Option 里沒有東西的時(shí)候,它的長度是 0(也就是 None)。

        for 循環(huán)

        如果我們把 Option 當(dāng)成一般的 List 來用,并且用一個(gè) for 循環(huán)來走訪這個(gè) Option 的時(shí)候,如果 Option 是 None,那這個(gè) for 循環(huán)里的程序代碼自然不會執(zhí)行,于是我們就達(dá)到了「不用檢查 Option 是否為 None 這件事。

        scala> val map1 = Map("key1" -> "value1")  map1: scala.collection.immutable.Map[String,String] = Map(key1 -> value1)    scala> val value1 = map1.get("key1")  value1: Option[String] = Some(value1)    scala> val value2 = map1.get("key2")  value2: Option[String] = None    scala> def printContentLength(x: Option[String]) {       |   for (c <- x){       |     println(c.length)       |   }       | }  printContentLength: (x: Option[String])Unit    scala> printContentLength(value1)  6    scala> printContentLength(value2)

        map 操作

        在函數(shù)式編程中有一個(gè)核心的概念之一是轉(zhuǎn)換,所以大部份支持函數(shù)式編程語言,都支持一種叫 map() 的動(dòng)作,這個(gè)動(dòng)作是可以幫你把某個(gè)容器的內(nèi)容,套上一些動(dòng)作之后,變成另一個(gè)新的容器。

        現(xiàn)在我們考慮如何用 Option 的 map 方法實(shí)現(xiàn) length: xxx 的輸出形式:

        先算出 Option 容器內(nèi)字符串的長度

        然后在長度前面加上 “length: ” 字樣

        最后把容器走訪一次,印出容器內(nèi)的東西

        scala> value1.map(_.length).map("length: " + _).foreach(println)  length: 6    scala> value1.map("length: " + _.length).foreach(println)  length: 6

        透過這樣「轉(zhuǎn)換」的方法,我們一樣可以達(dá)成想要的效果,而且同樣不用去做「是否為 None」的判斷。

        原文鏈接:https://www.jianshu.com/p/95896d06a94d

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 自拍偷自拍亚洲精品情侣| 亚洲精品乱码久久久久久蜜桃不卡| 鲸鱼传媒绿头鱼实验室之炮机测评日韩精品一级毛 | 亚洲午夜成人精品电影在线观看| 91人妻人人澡人人爽人人精品 | 亚洲情侣偷拍精品| 精品无码三级在线观看视频 | 伊人久久大香线蕉精品| 无码国产精品一区二区免费式芒果 | 精品国产一区二区三区2021| 精品久久777| 国内精品久久九九国产精品| 久久国产精品成人影院| 亚洲欧美国产精品第1页| 精品欧美| 国产在线精品福利大全| 99久久精品国产一区二区三区 | 无码精品视频一区二区三区| 欧美激情视频精品一区二区| 国产乱人伦偷精品视频| 亚洲欧美日韩精品| 国产精品免费观看| 成人久久精品一区二区三区| 精品人妻久久久久久888| 久久精品国产第一区二区三区| 亚洲高清国产拍精品26U| 无码日韩精品一区二区人妻| 拍国产乱人伦偷精品视频| 久久久久人妻一区精品果冻| 国产精品国产三级国产AⅤ| 99久久精品国产一区二区蜜芽| 亚洲一区精品中文字幕| 欧美成人精品一级高清片| 精品一区二区久久久久久久网站| 国产精品爽黄69天堂a| 麻豆精品不卡国产免费看| 欧美精品1区2区| 国产国拍亚洲精品福利| 国产三级精品久久| 久久免费国产精品| 亚洲精品tv久久久久|