views:

157

answers:

3

I am writing the constructor for my "main" class. The first thing it does is call a method to use commons-cli to parse the command line. If the parseOptions method returns false, an error has occurred, and the constructor should exit.

I tried writing the following code

if (!parseOptions(args)) return

but the compiler complains that I have a "Return statement outside method definition".

Short of calling System.exit(1) or inverting the boolean (and putting all of the rest of my logic inside the if statement, is there any way to return "early" from a constructor?

I suppose I could have the parseOptions method throw an IllegalArgumentException and catch that in my Main object.

Thanks.

+9  A: 

Dont try to do a early/premature return, this makes your code harder more complex, since the side effects of the return can be hard to understand. Instead use a exception to signal that something is wrong.

You can use require in the constructor. This doesn't return. But it seems like throwing an exception actually fits his situation better.

As in:

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)

Quote:

"We have these giant test suites, and we run them every time we change a little thing. Because we don't know if we change something over here it is not going to break something over there. And we can't know!" - Rich Hickey, Are We There Yet?, 2009

oluies
This doesn't _return_. But it seems like throwing an exception actually fits his situation better.
Alexey Romanov
+9  A: 

is there any way to return "early" from a constructor

No. But in your case it sounds like bad design, anyway.

If the parseOptions method returns false, an error has occurred

In this case the constructor should throw an exception, not return normally.

Alexey Romanov
After rethinking (and implementing it using `IllegalArgumentException`), I agree that a bad command line parse deserves an exception.
Ralph
+3  A: 

A constructor should always either complete fully, or abort (throw an exception). Anything else leaves your object "half constructed" and thus impossible to reason about.

If in your case, the object is valid even if parseOptions failed, then you can change the condition and continue:

if (parseOptions(args)) {
  // rest of constructor
}
IttayD
@IttayD, the fact that Scala doesn't support return from constructor doesn't mean it's 'impossible to reason about'.Replace `if (X) return;...` with `if (!x) {...}` and you'll be able to reason as much as you wish.
Elazar Leibovich
Huh? didn't you see that reversing the 'if' is exactly what I suggested? What I said that a constructor should finish or roll-back by throwing an exception. It can't return leaving things undone.
IttayD