Is there a way to make sure classes implementing an Interface implement static methods?

Tobias Kienzler picture Tobias Kienzler · Apr 22, 2010 · Viewed 18.8k times · Source

First of all, I read erickson's useful reply to "Why can’t I define a static method in a Java interface?". This question is not about the "why" but about the "how then?".


Edit: my original example was ill-posed, but I'll leave it below.

While I am now convinced that in most cases what I want to do is overkill, there is one scenario where it could be needed:

I'll take the ParametricFunction example again. Now let's take a complicated function, like the Bessel functions, where a lookup-table is appropriate. That has to be initialised, so the two options are passing the parameters directly to the constructor or providing a init(double[] parameters). The latter has the disadvantage that getValue(double x) must check the initialisation every call (or the ArrayIndexOutOfBoundsException must be considered as initialisation-check), so for time-critical applications I'd prefer the constructor-method:

interface ParametricFunction {
  public double getValue(double x);
}

class BesselFunction implements ParametricFunction {
  public BesselFunction(double[] parameters) { ... }
  public double getValue(double x) { ... }
}

Which touches another problem, the impossibility of constructors in interfaces. What would be a good solution there? I could of course use the init(double[] parameters) approach, but I mentioned my reason why not.
(Edit: OK, here an abstract class implementing the interface would do)

Now let's assume the ParametricFunction allows only certain parameters, e.g. positive integers. How to check the vailidity of parameters passed to the constructor? Throwing an IllegalArgument-exception would be a possibility, but a checkParametersValidity(double[] parameters) seems a lot more convenient. But checking the parameters needs to be done before construction, so it has to be a static method. And that's where I'd really like to know a way to make sure every class implementing the ParametricFunction interface does define this static method.

I know this example is rather artificial, and the reason for not simply using a init method through the interface is debatable, I'd still like to know the answer. Consider it an academic question if you don't like it.

(original example)

So basically I want one Interface to provide both usual methods and e.g. a getSimilarObject method. For (a made up) example

public interface ParametricFunction {
  /** @return f(x) using the parameters */
  static abstract public double getValue(double x, double[] parameters);

  /** @return The function's name */
  static abstract public String getName();

  /** @return Whether the parameters are valid  [added on edit] */
  static abstract public boolean checkParameters(double[] parameters);
}

and then

public class Parabola implements ParametricFunction {
  /** @return f(x) = parameters[0] * x² + parameters[1] * x + parameters[2] */
  static public double getValue(double x, double[] parameters) {
    return ( parameters[2] + x*(parameters[1] + x*parameters[0]));
  }
  static public String getName() { return "Parabola"; }
  // edit:
  static public boolean checkParameters(double[] parameters) {
    return (parameters.length==3);
  }
}

Since this is not allowed in the current Java standard, what is the closest thing to this?

The idea behind this is putting several ParametricFunctions in a package and use Reflection to list them all, allowing the user to pick e.g. which one to plot. Obviously one could provide a loader class containing an array of the available ParametricFunctions, but every time a new one is implemented one has to remember adding it there, too.

edit: An example to call it is

public double evaluate(String fnName, double x, double parameters) throws (a lot) {
  Class<ParametricFunction> c = (Class<ParametricFunction>) ClassLoader.getSystemClassLoader().loadClass(fnName);
  Method m = c.getMethod("getValue", x, parameters);
  return ((double) m.invoke(null));
}

and calling evaluate("Parabola", 1, new double[]{1,2,0});.

Answer

Donal Fellows picture Donal Fellows · Apr 22, 2010

You cannot require classes to implement particular static methods through an interface. It just makes no sense in Java terms. Interfaces force the presence of particular non-static methods in the classes that implement the interface; that's what they do.

The easiest way is definitely to have some sort of factory class that produces instances of the others. Yes, this does mean that you have to remember to keep that factory up to date when you add new instances, but since the first thing you do when you make a new implementation is test it (you do test it, yes?) you'll pick up on that problem very quickly!