lol
lol

Reputation: 49

How to write a constructor that prevents creation of objects on certain conditions

I am trying to create a constructor for an object that inherits another object, but this constructor should also prevent the creation of the object on certain conditions.

I have this code:

class Foo
{
    double x;
    public Foo(double init_x)
    {
        x = init_x;
    }
}

class Bar extends Foo
{
    public Bar(double init_x)
    {
        if(init_x < 10)
        {
            throw new Exception();
        }
        super(init_x);
    }
}

Here are the errors when the code is compiled with a main defined:

test2.java:13: error: constructor Foo in class Foo cannot be applied to given types;
        {
        ^
  required: double
  found: no arguments
  reason: actual and formal argument lists differ in length
test2.java:18: error: call to super must be first statement in constructor
            super(init_x);
                 ^
2 errors

My question is: why did I get the first error even though I clearly specified Bar(double init_x) and also for the second part if the super call has to be the first statement then how do I address this problem?

Upvotes: 1

Views: 151

Answers (3)

Ken Bekov
Ken Bekov

Reputation: 14015

I believe that throw exception in constructor is not good practice. Of cause, this is just my opinion, but I think, it will be better to make simple factory method:

class Bar extends Foo
{
    //hide constructor
    private Bar(init_x){
        super(init_x);
    }

    //factory method
    public static Bar createBar(double init_x)
    {
        if(init_x >= 10)
        {
            return new Bar(init_x);
        }else{
            //you can return null, instead of throwing exception
            throw new Exception();            
        }
    }
}

And when you need instance of bar:

public static void main(String [] args){

    Bar bar = Bar.createBar(104.3);
    ...
}

Upvotes: 0

Erwin Bolwidt
Erwin Bolwidt

Reputation: 31269

You have two options:

  1. You move the check until after the call to super. It's still before the method completes, so the caller will not see the object constructed - it prevents the construction at least in the view of the caller:

    class Bar extends Foo {
        public Bar(double init_x) throws Exception {
            super(init_x);
            if (init_x < 10) {
                throw new Exception();
            }
        }
    }
    
  2. You do the check in another method that returns the value if it is correct, but throws an exception if it is not correct:

    class Bar extends Foo {
        private static double checkInitX(double init_x) throws Exception {
            if (init_x < 10) {
                throw new Exception();
            }
            return init_x;
        }
    
        public Bar(double init_x) throws Exception {
            super(checkInitX(init_x));
        }
    }
    

    You are allowed to call as an expression within the call to super any method that's not an instance method on the object that you're constructing. A good place to put that method is as a static method in the class.

But usually, option 1 is the best. Unless there is a very good reason not to call the super with an out-of-range value (like, the super constructor is very slow, or it throws another, confusing, exception if the value is out of range), option 2 is not necessary. (In the two cases mentioned, you're better off refactoring the superclass constructor)

Upvotes: 2

NilsH
NilsH

Reputation: 13821

The answer is stated in the error message you get: error: call to super must be first statement in constructor

Upvotes: 0

Related Questions