scala - 函数可以返回不共享共同祖先的多种类型之一吗?

标签 scala

当然,我意识到所有类型都有一个共同的祖先,但我的意思是:

在动态类型语言中,具有“混合”返回类型是一种常见的做法。一个常见的情况是一个函数尝试从数据库中检索数据,然后返回一个对象(用找到的数据初始化)或 FALSE(如果没有找到数据)。

一个小伪代码来演示这种反模式:

function getObjectFromDatabase(object_id) {
  if(result = db_fetch_object("SELECT * FROM objects WHERE id = %d", object_id) {
    return result
  } else {
    return FALSE
  }
}

如果为我的对象 id 找到数据,我将返回一个数据库记录作为对象。如果没有,我会得到一个 bool 值。然后,当然,由我(客户)来处理多种可能的返回类型。

是在 Scala 中为所有可能的返回类型找到一个共同祖先并将其声明为签名中的返回类型的唯一方法吗?
// Like so:
def getObjectFromDatabase(objectId: Int): Any = {
   val result = dbFetchObject("SELECT * FROM objects WHERE id = %d", object_id) 
   if(result) {
     return result
   } else {
     return false
  }
}

或者是否可以注释多种可能的返回类型?

(请注意,我不希望这样做,因为我希望强制函数返回类型尽可能明确。得知该语言禁止模棱两可的返回类型,这让我松了一口气,这就是我要问的原因。)

最佳答案

是的,使用 Either :

def getObjectFromDatabase(objectId: Int): Either[Boolean, DbResult] = {
   val result = dbFetchObject("SELECT * FROM objects WHERE id = %d", object_id) 
   if (result) Right(result) else Left(false)

}

getObjectFromDatabase(id) match {
  case Right(result) => // do something with result
  case Left(bool) => // do something with bool
}

或者,如果没有结果的情况不需要特定值,请使用 Option :
def getObjectFromDatabase(objectId: Int): Option[DbResult] = {
   val result = dbFetchObject("SELECT * FROM objects WHERE id = %d", object_id) 
   if (result) Some(result) else None
}

getObjectFromDatabase(id) match {
  case Some(result) => // do something with result
  case None => // do something about no results
}

参见托尼莫里斯的 Option Cheat Sheet最常用的方法列表,您可以调用 Option以及它们如何转化为模式匹配。

其他两个选择是 Validation 来自 scalaz 和 Try , Scala 2.10 中的新功能。

对于 Validation StackOverflow 上有一些非常好的答案,例如:Method parameters validation in Scala, with for comprehension and monads .

对于 Try看到这篇博文:The Neophyte's Guide to Scala Part 6: Error Handling With Try .同一作者在 Option 上有好帖子和 Either .

关于scala - 函数可以返回不共享共同祖先的多种类型之一吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14410275/

相关文章:

scala - 将元组附加到Scala中的缓冲区

scala - 名为 Scala 自类型仍然阴影 "this"?

scala - 单 token 前瞻的性能损失是多少?

scala - 字段 "features"不存在。 Spark ML

scala - Spark流: Broadcast variables, java.lang.ClassCastException

scala - 如何使用 LabelledGeneric 一般更新案例类字段?

scala - 覆盖 toString 时如何使用条件语句

scala - 在 IntelliJ 中调试 scala sbt 集成测试

Scala Play 表单验证 : required boolean isn't mandatory

到目前为止我无法理解的 scala slick 方法