2016-08-30 66 views
1

比方說,我有這樣的代碼:`getOrElse`停止進程或返回不同的類類型

val parsedMessage: JsResult[Message] = Json.fromJson(Json.parse(msg)) 

val message: Message = parsedMessage.getOrElse { 
    log.warning("Invalid json: {}", msg) 
    RejectedMessageEvent(msg) 
} 

val newMessageEvent: NewMessageEvent = NewMessageEvent (userId, message.to, message.text) 

messagePersistentActor ! message 

顯然,這無法在編譯時間,因爲getOrElse不返回Message類型的對象。但是,讓我們假設,出於某種原因,parsedMessage失敗,我進入getOrElse的'else'部分。在這裏,我想要停止進程(在Java中它將是一個return)或返回一個RejectedMessageEvent - 如預期的那樣給出編譯錯誤。

作爲一個典型的Java開發人員,我很熱衷於使用:

if(parsedMessage.isError) { 
    log.warning("Invalid json: {}", msg) 
    messagePersistentActor ! RejectedMessageEvent(msg) 
} 
else { 
    val newMessageEvent: NewMessageEvent = NewMessageEvent (userId, message.to, message.text, UUID.randomUUID().toString, DateTime.now.getMillis) 
    messagePersistentActor ! message 
} 

但我覺得這不是斯卡拉的最佳實踐。

你會如何解決這種情況,我要麼停止getOrElse中的進程,要麼返回一個不同於此變量聲明的對象類型的對象類型?

我知道我可以在val message: Message = parsedMessage.getOrElse忽略消息類型聲明,並使其簡單val message = parsedMessage.getOrElse,但後來我就沒法做message.tomessage.textNewMessageEvent案例類的構造函數,因爲message既可以是MessageRejectedMessageEvent類型。

我使用的情況下,類和我可以使用繼承(RejectedMessageEventNewMessageEvent都伸到Message),但我想避免這種情況的解決方案,去一個更實際的一個。

+0

什麼JSON庫是你在用嗎?玩? –

+0

是的,這是一個Play Framework項目 – dazito

+0

'fold'是一個無效和有效的函數,可以任意的副作用。對於Option.fold也是如此。 –

回答

2

這是Scala中很常見這種模式someOptValue.map(value => ...).getOrElse(...)更換if (someOptValue.isDefined) ... else ...

messagePersistentActor ! parsedMessage.map {msg => 
    NewMessageEvent (userId, msg.to, msg.text) 
}.getOrElse { 
    log.warning("Invalid json: {}", msg) 
    RejectedMessageEvent(msg) 
} 
2

您可以使用asOpt代替,併爲您的信息得到一個Option值:

val parsedMessage: JsResult[Message] = Json.fromJson(Json.parse(msg)) 

val message: Option[Message] = parsedMessage.asOpt 

message match { 
    case Some(m: Message) => messagePersistentActor ! m 
    case None => { 
    // Log and handle error 
    } 
}