How to force subclasses to set a variable in java?

B T picture B T · Feb 22, 2013 · Viewed 18.4k times · Source

I have a class which defines all of the basic parameters for a given screen. From here every screen in the application is a subclass of this. I need every screen (i.e. subclass) to set the value of a variable in its implementation (namely, each screen must define what level it is in a navigation tree).

Also, ideally, this variable should be final when it is set in the sub classes (I realise this probably isn't possible).

What is the best way to go about this? Is there a way to correctly enforce this type of behaviour in Java?

Answer

B T picture B T · Feb 22, 2013

@pst's comment lead to this solution.

This can't be done with a variable. But an abstract class can require that a particular method is implemented: this method could return the applicable value

From declaring an abstract function to set or return the variable, you can force any subclass to implement it correctly.

Next, the function must be called by every single subclass of the outer class. This implies that it must be done somewhere in the outer class. This can be done in the no-argument constructor of the outer class without having to worry about subclasses calling super:

Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem. (Java docs: Super)

Based on that, this solution will hold up and correctly force the variable to be set as long as either:

  1. No other constructor is created in the superclass (hence super can't be used in a subclass to call a different constructor instead)
  2. All other constructors in the superclass still call the default constructor internally

The code:

Superclass:

public abstract class SuperClass {
    // Variable all inner classes must set
    static int myVar = 0;

    public SuperClass() {
        myVar = giveValue();
    }

    public abstract int giveValue();
}

Subclass:

public class SubClass extends SuperClass {

    @Override
    public int giveValue() {
        return 5; // individual value for the subclass
    }

}