Default constructors in Java

JavaInheritanceConstructor

Java Problem Overview


I know I'm asking some serious 101 question here...

I have some class Foo and a class Bar that extends Foo. In Foo I have a constructor that takes a set of parameters that it sets to its fields. Deriving classes such as Bar will typically not need to modify this. Now my IDE is giving me "There is no default constructor available in Foo". From a bit of Googling this appears to be because "constructors are not inherited". So all nice and well, but how do I now get this to work without duplicating this constructor in every deriving class? I'm assuming there is a more sane approach?

Java Solutions


Solution 1 - Java

Use the super constructor:

public Bar(int a, double b, ...) {
    super(a, b, ...);
}

Solution 2 - Java

> So all nice and well, but how do I now get this to work without duplicating this constructor in every deriving class?

You do need to duplicate the constructor signatures - if you want the subclass to have constructors with the same signatures. But you don't need to duplicate the code - you just chain to the superclass constructor:

public Bar(int x, int y) {
    super(x, y);
    // Any subclass-specific code
}

Of course if you can work out the superclass parameters from a different set of parameters, that's fine. For example:

public Bar(int x) {
    super(x, x * 2);
    // Any subclass-specific code
}

You really need to work out what information is required to construct a Bar - that should dictate your constructors.

If this is a problem, it's possible that you're overusing inheritance. It's hard to say for sure without any idea of what your actual classes are, but you should look at using composition instead of inheritance. It's no panacea, but it can avoid this sort of thing.

Solution 3 - Java

No, there's no more "sane" approach. If your base class has no default constructor, then you must explicitly call the correct constructor from all the children classes.

Note this doesn't mean children classes need to have the exact same constructor than base class. For example this is perfectly valid:

class Foo {

    protected int a;
    protected int b;

    protected Foo(final int a, final int b) {
        this.a = a;
        this.b = b;
    }
}

class Bar extends Foo {

    protected Bar() {
        super(0,0);
    }
}

Solution 4 - Java

The problem is solved with this:

class Foo{
       Foo(int a, int b){}
}

class Bar extends Foo{
         //Here must be a constructor OR declare a constructor in Foo without parameters
         Bar(){super(1,1)} //this is an example

}

Other solution is:

class Foo{
   Foo(int a, int b){}
   Foo(){}
}

class Bar extends Foo{
}

Remember that if have a constructor with parameters in the SuperClass (in this case Foo), the implicit constructor on the child class (in this case Bar), always will have a implicit call to "Super()" (always have to be one unless explicit).

Solution 5 - Java

This error could also happen because you are calling your super constructor last. You might have to move it to be the first statement:

    public SectionsPagerAdapter(FragmentManager manager, List<Fragment> fragmentList) {
        mFragmentList  = fragmentList;
        super(manager);

    }

    public SectionsPagerAdapter(FragmentManager manager, List<Fragment> fragmentList) {
        super(manager); --> this should come first
        mFragmentList  = fragmentList;
    }

Solution 6 - Java

JVM will not provide a default constructor if you have provided one due to design reasons. What you can do define constructor in Bar with same signature and call super().

public Bar(int x,int y) {
    super(x,y);
}

Solution 7 - Java

If parameters are not required and/or have default values then you can define default constructor (without parameters):

class Foo
{
    public final int DEFAULT_A = 42;
    protected int a;
    protected int b;

    public Foo(final int a, final int b)
    {
        this.a = a;
        this.b = b;
    }

    // Is equal to new Foo(Foo.DEFAULT_A, 0);
    public Foo()
    {
        this.a = this.DEFAULT_A;
    }

}

class Bar extends Foo {}

class PiBar extends Bar
{
    public final int DEFAULT_A = Math.PI;

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJeroen De DauwView Question on Stackoverflow
Solution 1 - JavaarshajiiView Answer on Stackoverflow
Solution 2 - JavaJon SkeetView Answer on Stackoverflow
Solution 3 - Javam0skit0View Answer on Stackoverflow
Solution 4 - JavaGaston FloresView Answer on Stackoverflow
Solution 5 - Javalive-loveView Answer on Stackoverflow
Solution 6 - JavaAniket ThakurView Answer on Stackoverflow
Solution 7 - JavaVasilii SuricovView Answer on Stackoverflow