在 Scala 中编写此条件语句的最佳方法

Best way to write this conditional statements in scala

我有两个相同类型的对象,但我想使用这些对象调用方法,但取决于几个布尔值。

def myMethod(a: Boolean, b: Boolean, obj1: MyClass, obj2: MyClass): Future[Done] = {
    if(a) obj1.methodWhichReturnsFuture()
    if(b) obj2.methodWhichReturnsFuture()
}

这里方法#methodWhichReturnsFuture 有return typr Future[Done]。这显示错误,因为我在这里 returning Unit。我虽然创建了一个 'var' 并在两个方法调用中分配它,但看起来这不是一个好方法。这绝对是基本的,但我想知道实现它的更好方法是什么?谢谢

在 Scala 中,没有 elseif 只能针对 side-effect 执行,因此

的结果值
if (a) obj1.methodWhichReturnsFuture()

将被丢弃,结果是 Unit (()) 的单例值。 if (b) 语句中也会发生同样的情况(从技术上讲,() 将是 myMethod 的结果,但它与 if (a) 中的 () 相同) .

因此您需要添加 else 子句,这也会导致 Future[Done] 并确定如果 ab 都是true(此外,如果您希望同时调用 obj1obj2,则需要决定是顺序执行还是并行执行)以及 ab 为假。

谢天谢地,因为 Done 是一个单例(就编码“这件事”而言,它与 Unit 基本相同,但在某种程度上更适合 Java 代码使用 Akka),有一个合理的默认值 Future[Done]Future.successful(Done)(基本上可以解释为“是的,当然,我做到了(但实际上没有什么可做的)”)。

所以如果你想同时进行 obj1obj2 调用(或者至少没有定义的“happens-before”关系),你可以这样写:

val obj1Fut = if (a) obj1.methodWhichReturnsFuture() else Future.successful(Done)
val obj2Fut = if (b) obj2.methodWhichReturnsFuture() else Future.successful(Done)

// exploits eagerness of Future, won't complete until both obj1Fut and obj2Fut have completed
obj1Fut.flatMap(_ => obj2Fut)

如果您不想在 obj1 调用之前执行 obj2 调用:

val obj1Fut = if (a) obj1.methodWhichReturnsFuture() else Future.successful(Done)

obj1Fut.flatMap { _ =>
  if (b) obj2.methodWhichReturnsFuture()
  else Future.successful(Done)
}

请注意,在您提供的 Unit 返回代码中,obj2 未来很有可能在 obj1 的未来完成之前完成。

如果您只想在 ab 都为真时执行 obj1 调用:

if (a) obj1.methodWhichReturnsFuture()
else if (b) obj2.methodWhichReturnsFuture()
else Future.successful(Done)

// or the equivalent pattern match, which might be more legible than if else if else
// (a, b) match {
//   case (true, _) => obj1.methodWhichReturnsFuture()
//   case (false, true) => obj2.methodWhichReturnsFuture()
//   case (false, false) => Future.successful(Done)
// }