【问题标题】:Early return from a Scala constructor从 Scala 构造函数提前返回
【发布时间】:2010-08-23 12:39:43
【问题描述】:

我正在为我的“主”类编写构造函数。它做的第一件事是调用一个方法来使用 commons-cli 来解析命令行。如果parseOptions 方法返回false,则发生错误,构造函数应该退出。

我尝试编写以下代码

if (!parseOptions(args)) return

但是编译器抱怨我有一个“方法定义之外的返回语句”。

没有调用System.exit(1) 或反转布尔值(并将我的所有其余逻辑放在if 语句中,有没有办法从构造函数“提前”返回?

我想我可以让parseOptions 方法抛出一个IllegalArgumentException 并在我的Main 对象中捕获它。

谢谢。

【问题讨论】:

  • 虽然我同意其他答案,即如果无法将实例置于满足其类不变量的状态,则任何构造函数都不应正常返回,但我想知道您为什么反对使用 if ?
  • 如果我有几个条件都可以导致提前返回,我最终会得到一个if 级联很多级别的深度。
  • 所以?如果这是你的构造函数的逻辑,那就是你的构造函数的逻辑。通常还建议 不要 在您的构造函数中有很多复杂的逻辑。理想情况下,他们只是“记下”构成实例状态/值的值。
  • @Randall:我同意最后一点(非复杂构造函数)。

标签: scala constructor exit


【解决方案1】:

不要尝试提前/过早返回,这会使您的代码更加复杂,因为返回的副作用可能难以理解。而是使用异常来表示出现问题。

你可以在构造函数中使用require。这不回来了。但似乎抛出异常实际上更适合他的情况。

如:

class MyTest(
private var myValue: Int ){

    require(myValue > 0) // Connected to constructor

}

defined class MyTest

scala> val x = new  MyTest(10)
x: MyTest = MyTest@49ff4282

scala> val y = new MyTest(-10)
java.lang.IllegalArgumentException: requirement failed
        at scala.Predef$.require(Predef.scala:133)

【讨论】:

  • 这不会返回。但似乎抛出异常实际上更适合他的情况。
【解决方案2】:

有没有办法从构造函数中“提前”返回

没有。但无论如何,在你的情况下,这听起来像是糟糕的设计。

如果 parseOptions 方法返回 false,则发生错误

在这种情况下,构造函数应该抛出异常,而不是正常返回。

【讨论】:

  • 在重新考虑(并使用IllegalArgumentException 实现它)之后,我同意错误的命令行解析应该例外。
【解决方案3】:

构造函数应该始终要么完全完成,要么中止(抛出异常)。其他任何事情都会使您的对象“半构建”,因此无法推理。

如果在您的情况下,即使 parseOptions 失败,对象仍然有效,那么您可以更改条件并继续:

if (parseOptions(args)) {
  // rest of constructor
}

【讨论】:

  • Scala 不支持从构造函数返回的事实并不意味着它“不可能推理”。将if (X) return;... 替换为if (!x) {...},您将能够随心所欲地推理。
  • 嗯?你没看到颠倒'if'正是我建议的吗?我所说的构造函数应该通过抛出异常来完成或回滚。它不能返回而留下未完成的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 2012-08-07
  • 2013-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多