Java - Alternatives to forcing subclass to have a static method

Viewed 10222

I often find I want to do something like this:

class Foo{
public static abstract String getParam();
}

To force a subclasses of Foo to return a parameter.

I know you can't do it and I know why you can't do it but the common alternative of:

class Foo{
public abstract String getParam();
}

Is unsatisfactory because it requires you to have an instance which is not helpful if you just want to know the value of the parameter and instantiating the class is expensive.

I'd be very interested to know of how people get around this without getting into using the "Constant Interface" anti pattern.

EDIT: I'll add some more detail about my specific problem, but this is just the current time when I've wanted to do something like this there are several others from the past.

My subclasses are all data processors and the superclass defines the common code between them which allows them to get the data, parse it and put it where it needs to go. The processors each require certain parameters which are held in an SQL database. Each processor should be able to provide a list of parameters that it requires and the default values so the configuration database can be validated or initialised to defaults by checking the required parameters for each processor type. Having it performed in the constructor of the processor is not acceptable because it only needs to be done once per class not once per object instance and should be done at system startup when an instance of each type of class may not yet be needed.

5 Answers

You can use the factory pattern to allow the system to create 'data' instances first, and create 'functional' instances later. The 'data' instances will contain the 'mandatory' getters that you wanted to have static. The 'functional' instances do complex parameter validation and/or expensive construction. Of course the parameter setter in the factory can also so preliminary validation.

public abstract class Processor { /*...*/ }

public interface ProcessorFactory {
    String getName(); // The  mandatory getter in this example

    void setParameter(String parameter, String value);

    /** @throws IllegalStateException when parameter validation fails */
    Processor construct();
}

public class ProcessorA implements ProcessorFactory {
    @Override
    public String getName() { return "processor-a"; }

    @Override
    public void setParameter(String parameter, String value) {
        Objects.requireNonNull(parameter, "parameter");
        Objects.requireNonNull(value, "value");
        switch (parameter) {
            case "source": setSource(value); break;
            /*...*/
            default: throw new IllegalArgumentException("Unknown parameter: " + parameter);
        }
    }

    private void setSource(String value) { /*...*/ }

    @Override
    public Processor construct() {
        return new ProcessorAImpl();
    }

    // Doesn't have to be an inner class. It's up to you.
    private class ProcessorAImpl extends Processor { /*...*/ }
}
Related