Best way to initialize final field in an abstract class

Viewed 87

I have in mind two ways to initialize a final field in an abstract class and I have to pick the most elegant, correct and understandable for other developers way. There will be at least 10 implementations of my abstract class. Any ideas on which one should I choose?

First way:

public sealed abstract class GuiComponent permits DummyComponent {

    private final Node internalNode;

    //------Constructor

    protected GuiComponent() {
        internalNode = Objects.requireNonNull(initInternalNode());
    }

    //------Protected

    protected abstract Node initInternalNode();

    protected final Node getInternalNode() {
        return internalNode; //subclasses will use this
    }

}

public final class DummyComponent extends GuiComponent {

    @Override
    protected Node initInternalNode() {
        HBox hbox = new HBox();
        //some Node preparation
        return hbox;
    }

}

Second way:

public sealed abstract class GuiComponent permits DummyComponent {

    private final Node internalNode;

    //------Constructor

    protected GuiComponent(Node internalNode) {
        this.internalNode = Objects.requireNonNull(internalNode);
    }

    //------Protected

    protected final Node getInternalNode() {
        return internalNode; //subclasses will use this
    }

}

public final class DummyComponent extends GuiComponent {

    //------Constructor

    public DummyComponent() {
        super(initInternalNode());
    }

    //------Private

    private static Node initInternalNode() {
        HBox hBox = new HBox();
        //...
        return hBox;
    }

}
1 Answers

In my opinion, the second approach is better. The reason being that the GuiComponent constructor requests a Node, so it is easier to understand that a Node is in fact needed. This makes it explicit, while the other approach makes it implicit because unless you see GuiComponent code, you have no way to know that getInternalNode() method will be called in GuiComponent constructor. You can even say that it is a side-effect of this constructor, as we all know side-effects are usually better avoided in software development.

Related