`getOrElse`停止进程或返回不同的类类型

时间:2016-08-30 23:07:59

标签: scala

假设我有这段代码:

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
}

但我觉得这不是Scala的最佳做法。

如果我想要在getOrElse内停止进程,或者返回与该变量声明的对象类型不同的对象类型,您将如何解决这种情况?

我知道我可以在val message: Message = parsedMessage.getOrElse省略消息类型声明并简单地val message = parsedMessage.getOrElse,但是我将无法在message.tomessage.text上执行此操作NewMessageEvent案例类构造函数,因为message可以是MessageRejectedMessageEvent的类型。

我正在使用案例类,我可以使用继承(RejectedMessageEventNewMessageEvent扩展Message),但我正在尝试避免这种解决方案并寻求更多实用的。

2 个答案:

答案 0 :(得分:2)

在scala中使用此模式if (someOptValue.isDefined) ... else ...替换someOptValue.map(value => ...).getOrElse(...)非常常见:

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

答案 1 :(得分: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
  }
}