Jeffed
Jeffed

Reputation: 163

Calling both the default and super constructor in Java

I guess what I'd want is simply not possible, but I want to make sure. Say I have

public class bar {
    public bar() {

    }
    public bar(Object stuff) {
         // something done with stuff.
    }
}

and an extension

public class foobar extends bar {
    public foobar() {
        super();
        // some additional foobar logic here.    
    }
    public foobar(Object stuff) {
        // Do both the 
        // "some additional foobar logic" and 
        // "something done with stuff" here.
    }
}

How can I make the foobar(Object stuff) as simple as possible while also avoiding to duplicate code? I can't simply call super(stuff) as then "some additional foobar logic" isn't done, and I can't call just this() as then I don't do what I'd want to do with "stuff".

NOTE : I realized I don't actually need to do this in this case, so this is now here only for theoretical purposes.

Upvotes: 0

Views: 147

Answers (2)

thst
thst

Reputation: 4602

It may lead to cleaner code if you add an explicit init() function, that encapsulates the stuff you want to share between the constructors. Especially in your case, where you try to hop between constructors.

In the presented answer, the super() constructor is not executed. While super() is empty in your example, it is not neccessarily so in the future.

Also, you rely on super(foo) to handle foo == null properly. While it may be completely acceptable to throw an IllegalArgumentException for the superclass, it is not for your use-case. You are basically extending the contract to initialize the superclass properly, using the parameterized constructor with a null parameter.

Using the init-method approach, code duplication is reduced and superclass has no extended contract. You may dislike the style, though. The constructor chaining avoids the additional method.

public class foobar extends bar {
    public foobar() {
        super();
        initFooBar(null);
    }

    public foobar(Object stuff) {
        super(stuff);
        initFooBar(stuff);
    }

    public void initFooBar(Object stuff) {
        // some additional foobar logic here.    
        // "something done with stuff" here.             
    }
}

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1500525

You can only chain to one constructor. Typically the best approach is for the "less specific" constructors (the ones with fewer parameters) to chain to the "more specific" ones, with a single "master" constructor which is the only one with logic in:

public class FooBar extends Bar {
    public FooBar() {
        this(null); // Or whatever value you want for "stuff"
    }

    public FooBar(Object stuff) {
        super(stuff);

        // Initialization logic
    }
}

Upvotes: 5

Related Questions