Jeroen De Dauw
Jeroen De Dauw

Reputation: 10908

Default constructors in Java

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?

Upvotes: 71

Views: 84721

Answers (7)

live-love
live-love

Reputation: 52366

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;
    }

Upvotes: 2

Vasilii Suricov
Vasilii Suricov

Reputation: 954

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;

}

Upvotes: 0

Aniket Thakur
Aniket Thakur

Reputation: 68905

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);
}

Upvotes: 0

Gaston Flores
Gaston Flores

Reputation: 2467

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).

Upvotes: 3

m0skit0
m0skit0

Reputation: 25863

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);
    }
}

Upvotes: 6

Jon Skeet
Jon Skeet

Reputation: 1499860

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.

Upvotes: 25

arshajii
arshajii

Reputation: 129497

Use the super constructor:

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

Upvotes: 83

Related Questions