32

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});.

Community
  • 1
  • 1
Tobias Kienzler
  • 25,759
  • 22
  • 127
  • 221
  • 1
    Why does getValue have to be static ? You would be able to do exactly what you want if getValue wasn't static. – nos Apr 22 '10 at 08:50
  • Then I'd have to create an instance of the class. Correct me if I'm wrong, but regarding it's purpose that doesn't seem to be usefull here. – Tobias Kienzler Apr 22 '10 at 09:03
  • 2
    What's wrong is your design. It's not OO. parameters[] should be an instance field of the Parabola class, set and checked in the constructor, and used in the getValue() class. – Michael Borgwardt Apr 22 '10 at 09:17
  • I really don't see the problem in instantiating those classes, it's the simplest solution to this one. If you want to be able to deploy new ParametricFunction implementations dynamically to your application, you can indicate the compatible classes in the manifest file of the deployed jar. You of course need some code to enable this mechanism. On the other hand I don't see how the static interface methods would help here. – fish Apr 22 '10 at 09:18
  • @Michael: But now suppose I want to fit data points to a user-chosen function, now all I'd have to do is to call `fit(fnName, double[] x, double y[])` and the Fitter find the parameters. I know it's not OO, but what would be the advantage in that here? Ok, the trouble is now, why put the parameters in the Fitter which provides the static fit function... All right, you convinced me, I have to reconsider the design. – Tobias Kienzler Apr 22 '10 at 09:48
  • An interface allows passing "objects" of the same type of classes and then calling methods with the same names on them to get different results based on the class of that "object". So defining static methods in an interface would not be meaningful because the static methods live on the "class-level". – aderchox Mar 02 '21 at 16:50

9 Answers9

21

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!

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • 11
    Why does it make no sense? Can't an Interface demand classes to provide a `static public String getDescription()`? I do not confuse this with javadoc, what I mean is e.g. a GUI where the user picks the `ParametricFunction` to fit data to and may want to know what each Function does if the name alone is not so intuitive. And then consider the `ParametricFunction` to be something more complicated so that instantiation would consume really a lot of time, especially when offering a list with the descriptions for, say, 100 `ParametericFunction` s of which in the end only one would be picked. – Tobias Kienzler Apr 22 '10 at 10:57
  • 4
    It makes no sense because you call static methods on classes and not instances. There is no interest for both classes to share the exact same static method name since you don't call this method from the interface... What would you expect the getDescription() to return? The description of the class? Or the description of the current instance class? – Sebastien Lorber Apr 22 '10 at 12:17
  • Some object systems solve this by making the static methods be methods on the class object. Java didn't do this, deciding to be closer to C++ in this area. – Donal Fellows Apr 22 '10 at 12:34
  • 15
    @Sebastien: Why is there no interest for both classes to share the exact same static method name? Using reflection this might be the only way to make sure the method exists. I would like `getDescription()` to return the description of the class. Why should it change on different instances? That's why I'd like this method to be static and yet enforce in an Interface-like way that it is implemented. – Tobias Kienzler Apr 22 '10 at 12:50
  • 1
    I recently came across scenario in which I have to define `IFileSystemUtil` interface which will be implemented different file system specific classes. For example, if I have `XyzFileSystemUtil` implementing `IFileSystemUtil`, I will like those util classes implement certain functionality and since they are util classes, they need to be `static`. I believe it should be made possible to enforce this requirement through interface. – Mahesha999 Jul 26 '18 at 10:55
  • Static methods should be independent of state/externals, depending only on their arguments -- not class hierarchy or method names. If you want to enforce a structure like that on your utility classes, it should be via an external mechanism -- i.e., using reflection in a test to validate that they all have the given method signature. Which should be trivial, given that you need reflection to access them interchangeably anyways. That said, you really ought to reconsider going to such great lengths to make classes act like objects, when you could just use objects and instance methods. – Matthew Read May 23 '23 at 19:33
4

Why not try Java 5 enum? ie:

public enum ParametricFunctions implements ParametricFunction {
    Parabola() {
        /** @return f(x) = parameters[0] * x² + parameters[1] * x + parameters[2] */
        public double getValue(double x, double[] parameters) {
            return ( parameters[2] + x*(parameters[1] + x*parameters[0]));
        }

        public String getName() { return "Parabola"; }

        public boolean checkParameters(double[] parameters) {
            return (parameters.length==3);
        }
    },

    // other functions as enum members
}

With this you can look up the static function types easily, and with compile-time safety, but still allow the interface type to be referenced elsewhere. You could also place a method on the enum type to allow lookup of the function by name.


EDIT for concerns on file size with the enum way.

In that case you could define each function as it's own class, ie:

public class Parabola implements ParametricFunction {

    /** @return f(x) = parameters[0] * x² + parameters[1] * x + parameters[2] */
    public double getValue(double x, double[] parameters) {
        return ( parameters[2] + x*(parameters[1] + x*parameters[0]));
    }

    public String getName() { return "Parabola"; }

    public boolean checkParameters(double[] parameters) {
        return (parameters.length==3);
    }

}

Then you can have many separate, implementation files, and compose them into one, smaller, enum-like class through which the functions can be accessed statically. Ie:

public class ParametricFunctions {  
    public static final ParametricFunction parabola = new Parabola(),
                                           bessel = new BesselFunction(),
                                           // etc
}

This allows a single place to look up the functions, with the implementation kept separate. You could also add them to a static collection for name lookup. You could then maintain readability in your functions as mentioned in another comment:

import static ...ParametricFunctions.parabola;
// etc

public void someMethodCallingFit() {
    fit(parabola, xValues, yValues);
}
Grundlefleck
  • 124,925
  • 25
  • 94
  • 111
  • +1 for that idea. But unfortunately that result in a huge file if I started including BesselFunctions etc. which might really be better of in a separate class... – Tobias Kienzler Apr 22 '10 at 10:48
  • You can create multiple enums. They are used only to ensure that implementations are singletons. One natural development of this approach is grouping functions in the same enum in the UI somehow. – Ha. Apr 22 '10 at 11:05
  • @Ha: I was going to suggest multiple enums, but I don't think you can nest or group them without them being in the same file. Though I'm not sure if grouping them at compile-time is necessary, would be cool in this instance if you could do `ParametricFunctions.quadratic.Parabola` or `ParametricFunctions.logarithmic.SomeLogFunction`. Don't know if I'm reading too much into a made up example ;-) – Grundlefleck Apr 22 '10 at 11:13
  • 1
    @TobiasKienzler (late reply, for other people) you can also "hide" the processing in classes in other files and keep the enum file simple. I use the same in image processing where my image processors are in an enum file but the code is in other classes, called by the methods of the enum. – Matthieu Jan 31 '14 at 13:35
3

The idea behind this is putting several ParametricFunction's in a package and use Reflection to list them all, allowing the user to pick e.g. which one to plot.

That's going to fail for a more basic reason: reflection offers no way to list all classes in a package (because "all classes in a package" is not a well-defined set, due to the flexibility of the classloader mechanism).

The modern solution for this kind of thing is to make it part of the application configuration via a dependency injection framework.

Obviously one could provide a loader class containing an array of the available ParametricFunction's, but every time a new one is implemented one has to remember adding it there, too.

Well, with your concept, every time a new one is implemented, one is forced to put it into the same package. By putting it into a configuration file or a loader class (the same thing, really), you remove that restriction.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • well, I could do the evil thing and use the file system to list the package's directory... To me it makes perfect sense to put all `ParametricFunction`s into a package like `my.math.function.parametric`. But a configuration file would also require the class loader and providing an extended thing like (I'll edit the question right away) `static boolean checkParameters(...)` would still require the mechanism I asked for, no? – Tobias Kienzler Apr 22 '10 at 08:54
  • @Tobias: the config file would have a specific name and list the specific names of classes to be loaded - no problem there. As for that checkParameter() thing - that's just wrong. You're fundamentally misusing OO concepts. Classes are meant to have multiple instances with different state, not as a collection of static methods. – Michael Borgwardt Apr 22 '10 at 09:15
  • if not classes, what can I use as a collection of static methods? Does my own answer make things at least a bit better? – Tobias Kienzler Apr 22 '10 at 09:24
  • @MichaelBorgwardt "Classes are meant to have multiple instances with different state". That seems like a overly broad generalisation. This doesn't account for the singleton pattern. – slinden77 Jun 24 '16 at 08:17
3

Your answer to your own question can be simplified further. Keep the ParametricFunction interface as-is, and change Parabola into a singleton that implements ParametricFunction:

public class Parabola implements ParametricFunction {
  private static Parabola instance = new Parabola();

  private Parabola() {}

  static public ParametricFunction getInstance() {
    return instance;
  }

  public double getValue(double x, double[] parameters) {
    return ( parameters[2] + x*(parameters[1] + x*parameters[0]));
  }
  public String getName() { return "Parabola"; }
  public boolean checkParameters(double[] parameters) {
    return (parameters.length==3);
  }
}

Indeed, if there is no particular reason why Parabola needs to be a singleton class, you could get rid of the static method and attribute and make the constructor public.

The purpose of creating an instance of Parabola is to simplify your application.

EDIT in response to your question below:

You cannot use standard Java constructs to force a class to implement a static method with a given signature. There is no such thing as an abstract static method in Java.

You could check that a static method is implemented by writing a separate tool that runs as part of your build and checks either the source code or the compiled code. But IMO, it is not worth the effort. Any missing getInstance() will show up if you compile code that calls it, or at runtime if you try to use it reflectively. That should be good enough, in my opinion.

Besides, I cannot think of a convincing reason why you need the class to be a singleton; i.e. why the getInstance method is necessary.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    +1 Definitely less complicated than my way, thanks. But there's still no way to make sure that a new class, say `Gaussian`, will implement the `getInstance()` method, too. – Tobias Kienzler Apr 22 '10 at 09:52
2

The reason is readability: fit("Parabola", xValues, fValues) vs. fit(Parabola.getInstance(), xValues, fValues) vs. fit(new Parabola(), xValues, fValues). Why would I want to have an Instance of function defined entirely by it's arguments with no internal data?

Actually you are missing something about oriented object programming basics...

If you define an object Parabola, this object should represent a Parabola, and not a toolbox to check parameters are ok etc...

Your Parabola item should contain the parameters (x, y ...) and you could pass them with constructor...

double x;
double [] parameters;
public Parabola(double x, double[] parameters) {
  this.x = x;
  this.parameters = parameters;
}

Thus you shouldn't use parameters on your function since the parameters are now declared as class member attributes...

public double getValue() {
  return ( this.parameters[2] + x*(this.parameters[1] + x*this.parameters[0]));
}

Then just call

parabolaInstance.getValue();
Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
  • I know, but that would require a fit function to call `setParameters(parameters)` and `getValue(x)` everytime instead of simply `getValue(x, parameters)`. On the other hand, setParameters would be called only for a new fit and passing the parameters for every evaluation is a waste... I see. +1 – Tobias Kienzler Apr 22 '10 at 10:17
  • 1
    Actually why not doing something like this: Parabola parabola = new Parabola(x;y;z) fit(Parabola) with public void(or what you want) fit(ParametricFunction pamFunc) { // yourimpl } – Sebastien Lorber Apr 22 '10 at 10:21
  • +1 true indeed. But what about the problem I state in reply to Donal Fellows' answer? http://stackoverflow.com/questions/2689312/is-there-a-way-to-make-sure-classes-implementing-an-interface-implement-static-me/2689947#2689947 – Tobias Kienzler Apr 22 '10 at 11:04
0

One solution - is make all methods non-static with requirement that class must have default constructor. Then you can instantiate it easily and call methods you need.

Ha.
  • 3,454
  • 21
  • 24
  • 1
    @Ha: You mean like in the answer I've posted myself? I rethought it, but to me it just seems unnecessary to instantiate a class for which the possibility of several instances does not offer anything useful. – Tobias Kienzler Apr 22 '10 at 09:28
  • 1
    Yes, you lose 16 bytes to store the instance but gain a lot of speed because only constructor is invoked via reflection. – Ha. Apr 22 '10 at 10:23
  • I have seen this pattern used in eclipse. Mylyn connectors plugins provide class extending some abstract class and only single instance of the connector's class is created somewhere inside the mylyn via reflection. So is your case - only one reflection-aware singlton class will create all necessary instances and put them in the map. – Ha. Apr 22 '10 at 10:32
  • How do you make sure, at compile time, that a class has a default, zero-arg constructor? I'm **very** interested! – Matthieu Jan 31 '14 at 13:38
  • I don't know a way to check such thing at compile time. – Ha. Feb 17 '14 at 10:40
0

What you want to do is not ok...

You want to define static methods in an interface I and have some implementations A and B of this interface, with their own implementation of these static methods declared in the interface I.

Just imagine, how the computer would know what to do if you call I.staticMethod() ??? will it use the implementation of A or B?!!

The interest to declare a method in the interface is to use polymorphism and be able to call this method for different object implementations... But for static methods, since you don't call the method from an instance (actually you can but not really needed...) but with ClassName.xxxMethod, it absolutly has no interest...

Thus you don't have to put these static methods in the interface... just put them in the both implementations and call them with A.staticMethod() and B.staticMethod() (and they don't even need to share a same method name!)

I wonder how you want to call your static method, do you sample code to show?

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
  • I would never want to call I.staticMethod(), that's why I labeled it abstract, too. An example is in the now edited question. – Tobias Kienzler Apr 22 '10 at 09:37
  • So you would call A.staticMethod, or B.staticMethod... Thus you know at compile time on which class you call the method so why do you need to have a common interface with the static method? If you would call the static method on an object instance ( i.staticMethod (anyway not possible), a.staticMethod or b.staticMethod) then you'd better consider using non static methods... – Sebastien Lorber Apr 22 '10 at 10:16
  • 5
    Because I wanted A and B to implement that staticMethod *for sure* and make sure someone else using the Interface for a new class will do so, too. – Tobias Kienzler Apr 22 '10 at 10:45
0

@Sebastien: Why is there no interest for both classes to share the exact same static method name? Using reflection this might be the only way to make sure the method exists. I would like getDescription() to return the description of the class. Why should it change on different instances? That's why I'd like this method to be static and yet enforce in an Interface-like way that it is implemented. – Tobias Kienzler 3

As i already said declaring the method static means you can call it directly from the class and don't need a class instance. Since it has no sense to call I.staticMethod() (as already explained), you just can call A.staticMethod1() and B.staticMethod2(), their name doesn't matter at all since you call them from the A or B class, known at compile time!

If you want a getDescription to return the same description no matter the instance of ParametricFunction concerned, just make the ParametricFunction an abstract class and implement the static methods directly in this class. Then you'll be able to call A, I or B.getDescription(); (even a,i or b...). But it remains the same than implementing it in A and B and calling it threw A or B...

Calling a static method from an instance is not a good practice and has no interest, so you should call A.meth(), or B.meth() and not a.meth() or b.meth()

Because I wanted A and B to implement that staticMethod for sure and make sure someone else using the Interface for a new class will do so, too. – Tobias Kienzler 5 hours ago

Actually "someone else" will normaly not call a.meth() or b.meth() thus if he makes a class C and want to call the C.meth() he'll never be able to do that because C.meth() is not implemented or not static... so he will do it, or the C.meth() would never been called and then it is also non sense to force developpers to implement static functions that would never be used...

I don't know what i can add...

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
0

Constructor in interface? uh? Would you like to be able to call Interface i = new Interface(double[] parameters)? And the computer would another time choose himself the implementation? This is as much strange as static in interface :D

As you said, checking parameters should be done before construction... But this doesn't mean you can't raise exception on construction if parameters are not ok. It's just a security you can add, that will ensure that the constructed object will be coherent. But such code doesn't allow you to bypass a previous validation: raising exception on construction will tell you "hey you have a bug!" while not validating the params will just tell you "hoho someone using GUI tried to set a bad value, we'll send him an error message..."

Actually, since you need to validate the values, and the object is not even constructed, why do you absolutly want to add this validation on the model object? Form/Gui/whatever validation could be done anywhere, in a validation java class... Just set a static (or not) method, in another class called ParametricFunctionValidationHelper, where you add your method and the validation implementation.

public static boolean validateParametricFunction(String functionType, double[] parameters) {
  if ( functionType.equals("bessel") ) return validateBessel(parameters);
  if ( functionType.equals("parabola") ) return validateParabola(parameters);
}

It doesn't matter how is represented your functionType (i choose String because i suppose you get it from user interface, web or gui... it could have been Enum...

You can even validate the object after having constructed it:

public static boolean validateParametricFunction(ParametricFunction pamFunc) {
  if ( pamFunc instanceOf BesselFunction ) return validateBessel(pamFunc.getParameters);
  ......
}

You can even put static validation methods in function classes and then you'll have: public static boolean validateParametricFunction(ParametricFunction pamFunc) { if ( pamFunc instanceOf BesselFunction ) return BesselFunction.validateBessel(pamFunc.getParameters); if ( pamFunc instanceOf ParabolaFunction ) return ParabolaFunction.validateParabola(pamFunc.getParameters); }

Yes you won't be able to set the static method in the interface but anyway how would you call such a method?

With code like

public static boolean validateParametricFunction(ParametricFunction pamFunc) {
  return ParametricFunction.validate(pamFunc);
}

??? This as no sense because the JVM won't be able at all to know which implementation of the static method to use since you don't call the static method from an instance but from a class! It as only sense if you implement the validate method directly in the ParametricFunction class, but anyway if you do such a thing you'll have to do exactly the same that i've shown you before with the instanceOf, because the instance of the pamFunc is the only item you'll have to select which kind of validation you'll have to use...

That's why you'd better use a non static method and put it in the interface like:

public static boolean validateParametricFunction(ParametricFunction pamFunc) {
  return pamFunc.validate();
}

Actually what you should do is: - Retrieve parameters (String?) from GUI / Web interface / anything - Parse String parameters in good format (String to int...) - Validate these parameters with a validation class (static method or not) - If no validation -> print message to user - Else construct object - Use the object

I don't see anywhere a need of static method in interface...

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419