用scala有一年多了,對於scala中的Option和Try使用的較爲頻繁,對其應用場景相對熟悉一些。而對於Either,仔細回想一下卻發現幾乎(徹底)沒有使用過,其實並非沒有遇到過Either的使用場景,只是遇到的時候不知道可以使用Either來解決此問題。
昨天在網上偶然看到一篇介紹Either的文章,發現有一種場景可使用Either來解決,具體是這樣的:
html
web系統中,Controller層調用service層方法,根據郵箱查詢註冊的用戶User,若是未取到User,則須要知道是什麼緣由致使的。
定義一個方法,根據登陸郵箱查詢User對象,方法簽名如: def getUserByEmail(email:String):Userweb
注意方法的返回值類型,這裏返回的是User對象。在運行時會發生以下三種狀況:post
一、正常返回null url
二、正常返回User spa
三、發生異常拋出Exception。scala
對於狀況1,調用處若是想知道是爲何返回了null,是由於email的格式錯誤?仍是由於該email沒有註冊的用戶? 該種方法簽名是沒辦法把失敗緣由返回給調用處的 。
那麼咱們考慮可否把返回結果類型User修改成Try[User],即:def getUserByEmail(email:String):Try[User]
對於剛纔的狀況1,若是是由於email格式不對,咱們在方法體內能夠封裝一個Failure(RuntimeException("郵箱格式錯誤"))返回給調用處。而若是是該郵箱未註冊,未查詢到該用戶,若是再封裝一個Exception就不合適了。由於查不到用戶屬於正常的邏輯,不屬於異常範疇,這種方式是不可取的。
那麼咱們再考慮把返回值類型Try[User]修改成Option[User],即:def getUserByEmail(email:String):Option[User]
這樣,只是把把返回結果null修改成None,並未達到咱們想要的目的
這時,咱們就能夠考慮把返回值類型修改成Either[String,User],即:def getUserByEmail(email:String):Either[String,User]。code
若是查詢到User,那麼返回一個Right(user)便可,若是郵箱格式錯誤,則返回一個Left("郵箱格式錯誤"),若是該郵箱未進行註冊,則返回Left("該郵箱未進行註冊");若是運行中發生Exception,能夠直接拋出,也能夠封裝爲Left("發生XXX異常")返回給調用處。
除了經過Either來返回失敗信息,咱們也可使用Tuple2[String,User]類型來實現想要的結果,在失敗的時候返回Tuple2("失敗緣由描述",null),只是相對於Either來講,不是那麼便捷。htm
使用方式可見以下僞代碼:對象
1 @Test 2 def testEither(): Unit = { 3 getUserByEmail("xxx@sina.com") match { 4 case Right(user) => ??? 5 case Left(msg) => println("查詢用戶失敗,緣由:" + msg) 6 } 7 } 8 9 def getUserByEmail(email: String): Either[String, User] = { 10 if (email無效) { 11 return Left("郵箱格式錯誤") 12 } else { 13 if (未查詢到註冊郵箱) { 14 return Left("該用戶不存在") 15 } else { 16 return Right(user) 17 } 18 } 19 }
=========================================blog
原文連接:scala中Either的一種使用場景
=========================================
-------end