Java - how to call different super() according to inheriting class's constructor argument?

StackOverflow https://stackoverflow.com/questions/20999559

  •  25-09-2022
  •  | 
  •  

Question

I am trying to make the inheriting class ask for less arguments, and calculate the 'correct' mising arguments for the super class. Looking for help on how to do this, without using factory methods.

This is an example code to simplify things. Son(int) will call super(int,boolean) based on the value of int.

class Base {
  ...
  public Base (int num, boolean boo2) { ...}
  ...
}

class Son extends Base {
  ...
  public Son (int num) {
    if (num > 17)
       super(num, true);
    else
      super(num , false);
  }
  ...
}

I also considered making Base an interface, but that doesn't allow me to enforce some argument correctness checks.

Appreciate your help.

Was it helpful?

Solution 2

If finding the other arguments is a complex operation (i.e., cannot be reduced to a single expression) you can add a static method that do that for you and refer to it in the super call, something like:

Class Son extends Base {

  private static boolean getMyBoolean(int num) {
    return num > 17; //or any complex algorithm you need.
  }

  public Son (int num) {
    super(num, getMyBoolean(num));
  }
  ...
}

Otherwise, if the missing arguments can be calculated using a simple expression (as in the concrete example you give), just write:

Class Son extends Base {
  public Son (int num) {
    super(num, num > 17);
  }
  ...
}

OTHER TIPS

I'm not 100% sure, but could this work?

class Son extends Base {
  ...
  public Son (int num) {
       super(num, (num>17));
  }
  ...
}

The super() call must be the first statement in the constructor. In this case you can use:

class Base {
    public Son(int num) {
        super(num, num > 17);
    }
}

If the calculation work that you need to do is longer than a single expression, you can move it into a static method that you call from the constructor:

class Son extends Base {
    public Son(int num) {
        super(num, calcBoo(num));
    }

    private static boolean calcBoo(int num) {
        if (num > 17)
            return true;
        else
            return false;
    }
}

Another option is to hide the constructor and add a static factory method, which would let you do arbitrarily complex work before calling the super constructor:

class Son extends Base {
    private Son(int num, boolean boo) {
        super(num, boo);
    }

    public static Son create(int num) {
        boolean boo;
        // ... statements here ... //
        return new Son(num, boo);
    }
}

Note that constructor call must be the first statement in a constructor. So you need to:

public Son (int num) {
   super(num, (num>17));
}

This will do the same thing, since num > 17 will be evaluated to true or false, and it's the first statement in the constructor, so it'll compile.

See the docs:

Invocation of a superclass constructor must be the first line in the subclass constructor.

The first line in a constructor has to be a call to super, or else you can't have it.

Why not push the behavior up to the Base class? That would be a better way to solve this problem anyway.

So you would have something like:

Son {
  super(num,17); //in base, you have a "break point" parameter
  ....
}

From the JLS §8.8.7:

The first statement of a constructor body may be an explicit invocation of another constructor of the same class or of the direct superclass (§8.8.7.1).

ConstructorBody:
    { ExplicitConstructorInvocationopt BlockStatementsopt }

The call to super() must be the first statement of your constructor. Luckily, in your case there is an easy way to condense it, as has already been mentioned:

public Son(int num) {
    super(num, num > 17);
}

I assume you're asking about the requirement that the call to super be the first line in your constructor.

You could either use a simple boolean expression like the other answers, or you could generalize the solution (in case your example was just that, an example) and use an inline-function call that returns the correct value. You might also check out the ternary operator.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top