1

Class A derives from abstract class B and implements the abstract method foo. Now in method foo I want to do something which depends on a member variable of class A, mType. However this results in a bug because foo is called in the constructor from abstract class B, hence mType isn't initialised yet.

It is not possible to initialise mType before the super() so I don't know a good and clean way to go about this. Of course I can make mType a member of B but I think this isn't a good way to go because mType doesn't have anything to do with this class, in this example this is perhaps not clear, but of course I've rewritten the practical situation to a short simple one in order to explain the problem.

What is a good way to tackle this problem?

public abstract class B {
    public B() { 
        foo(); // A::mType IS NOT INITIALISED!!
    }

    protected abstract void foo();
}

private class A extends B {
    public enum Type { TYPE1, TYPE2 };

    public A(Type aType) {
        super();
        mType = aType;
    }

    @Override
    protected void foo() {
        if (mType == Type.TYPE1) {
            // ..
        } else {
            // ...
        }
    }
}
Gio
  • 3,242
  • 1
  • 25
  • 53
  • 3
    [Never call overridable methods from a constructor](http://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-constructors). – Seelenvirtuose Sep 25 '14 at 08:28
  • You could just do whatever setup code you're doing in `foo()` in the constructor? Why override it if you're just calling it immediately anyway? – Evan Knowles Sep 25 '14 at 08:29
  • Bad practice of calling overridable methods in constructor, but if you *must*, you could change the signature of `foo` to take `foo(Type)` and do everything you want there, i.e. assign your member and do your other checking etc. – webuster Sep 25 '14 at 08:54

1 Answers1

0

Agreeing on the comment made by Seelenvirtuose, I'm going answer my question. It is indeed bad practice to call overridable methods in the constructor. The following solves the problem:

public abstract class B {
    public B() { }

    protected abstract void foo();

    protected void init() {
        foo();
    }
}

private class A extends B {
    public enum Type { TYPE1, TYPE2 };

    public A(Type aType) {
        super();
        mType = aType;
        init();
    }

    @Override
    protected void foo() {
        if (mType == Type.TYPE1) {
            // ..
        } else {
            // ...
        }
    }
}

At first sight it may perhaps seem impractical, why not simply call foo in the constructor of class A. But in my real practical situation it is rather more complex, various overrided methods need to be called in a certain sequence. The base class needs to provide a method for this in order to avoid code duplication. Adding a simple init method which is called from the derived class tackles this problem.

Gio
  • 3,242
  • 1
  • 25
  • 53