Scala教程之:Either
在之前的文章中我們提到了Option,scala中Option表示存在0或者1個(gè)元素,如果在處理異常的時(shí)候Option就會(huì)有很大的限制,因?yàn)镺ption如果返回None,那么我并不知道具體的異常到底是什么,這樣scala引入了Either。
顧名思意,Either表示或者是這一個(gè)元素或者是那個(gè)元素。這樣在異常處理的時(shí)候就非常有用了。
我們先看一下Either的定義:
sealed abstract class Either[+A, +B] extends Product with Serializable它有兩個(gè)子類Left和Right:
/** The left side of the disjoint union, as opposed to the [[scala.util.Right]] side.** @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse*/ final case class Left[+A, +B](@deprecatedName('a, "2.12.0") value: A) extends Either[A, B] {def isLeft = truedef isRight = false@deprecated("Use .value instead.", "2.12.0") def a: A = value }/** The right side of the disjoint union, as opposed to the [[scala.util.Left]] side.** @author <a href="mailto:research@workingmouse.com">Tony Morris</a>, Workingmouse*/ final case class Right[+A, +B](@deprecatedName('b, "2.12.0") value: B) extends Either[A, B] {def isLeft = falsedef isRight = true@deprecated("Use .value instead.", "2.12.0") def b: B = value }我們通過(guò)這兩個(gè)子類從兩個(gè)可能的元素中選擇一種。
Either 概念的產(chǎn)生時(shí)間早于Scala。很長(zhǎng)時(shí)間以來(lái)它被認(rèn)為是拋出異常的一種替代方案。
為了尊重歷史習(xí)慣,當(dāng)Either 用于表示錯(cuò)誤標(biāo)志或某一對(duì)象值時(shí),Left 值用于表示錯(cuò)誤標(biāo)志,如:信息字符串或下層庫(kù)拋出的異常;而正常返回時(shí)則使用Right 對(duì)象。很明顯,Either 可以用于任何需要持有某一個(gè)或另一個(gè)對(duì)象的場(chǎng)景中,而這兩個(gè)對(duì)象的類型可能不同。
我們看下怎么用Either的常規(guī)使用:
def positive(i: Int): Either[String,Int] = if (i > 0) Right(i) else Left(s"nonpositive number $i")for {i1 <- positive(5).righti2 <- positive(10 * i1).righti3 <- positive(25 * i2).righti4 <- positive(2 * i3).right } yield (i1 + i2 + i3 + i4) // Returns: scala.util.Either[String,Int] = Right(3805)for {i1 <- positive(5).righti2 <- positive(-1 * i1).right // EPIC FAIL!i3 <- positive(25 * i2).righti4 <- positive(-2 * i3).right // EPIC FAIL! } yield i1 + i2 + i3 + i4 // Returns: scala.util.Either[String,Int] = Left(nonpositive number -5)再看一下Either怎么在代碼中消除程序錯(cuò)誤,將錯(cuò)誤封裝在Either中。
scala> def addInts(s1: String, s2: String): Int = | s1.toInt + s2.toInt addInts: (s1: String, s2: String)Int scala> for { | i <- 1 to 3 | j <- 1 to i | } println(s"$i+$j = ${addInts(i.toString,j.toString)}") 1+1 = 2 2+1 = 3 2+2 = 4 3+1 = 4 3+2 = 5 204 | 第7 章 3+3 = 6 scala> addInts("0", "x") java.lang.NumberFormatException: For input string: "x"先看上面的例子,我們定義了一個(gè)addInts方法,接收兩個(gè)String參數(shù),并將其轉(zhuǎn)換為Int。如果兩個(gè)參數(shù)都是可以轉(zhuǎn)換的字符串當(dāng)然沒(méi)問(wèn)題,但是如果輸入了一個(gè)無(wú)法轉(zhuǎn)換的字符串就會(huì)報(bào)異常。
雖然異常有時(shí)候是好事情,但是異常會(huì)阻止程序的正常運(yùn)行。我們看下怎么用Either來(lái)將其封裝起來(lái):
scala> def addInts2(s1: String, s2: String): Either[NumberFormatException,Int]= | try { | Right(s1.toInt + s2.toInt) | } catch { | case nfe: NumberFormatException => Left(nfe) | } addInts2: (s1: String, s2: String)Either[NumberFormatException,Int] scala> println(addInts2("1", "2")) Right(3) scala> println(addInts2("1", "x")) Left(java.lang.NumberFormatException: For input string: "x") scala> println(addInts2("x", "2")) Left(java.lang.NumberFormatException: For input string: "x")按照上面的設(shè)計(jì),Either封裝好了異常,不會(huì)影響程序的正常運(yùn)行,而且可以返回具體的錯(cuò)誤信息,實(shí)在是一個(gè)不錯(cuò)的設(shè)計(jì)方式。
更多精彩內(nèi)容且看:
- 區(qū)塊鏈從入門(mén)到放棄系列教程-涵蓋密碼學(xué),超級(jí)賬本,以太坊,Libra,比特幣等持續(xù)更新
- Spring Boot 2.X系列教程:七天從無(wú)到有掌握Spring Boot-持續(xù)更新
- Spring 5.X系列教程:滿足你對(duì)Spring5的一切想象-持續(xù)更新
- java程序員從小工到專家成神之路(2020版)-持續(xù)更新中,附詳細(xì)文章教程
更多教程請(qǐng)參考 flydean的博客
總結(jié)
以上是生活随笔為你收集整理的Scala教程之:Either的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: @SessionAttributes 和
- 下一篇: Scala教程之:深入理解协变和逆变