views:

3324

answers:

13

Here's the example:

public interface IXMLizable<T>
{
  public static T newInstanceFromXML(Element e);
  public Element toXMLElement();
}

Of course this won't work. But why not?

One of the possible issues would be, what happens when you call:

IXMLizable.newInstanceFromXML(e);

In this case, I think it should just call an empty method (i.e. {}). All subclasses would be forced to implement the static method, so they'd all be fine when calling the static method. So why isn't this possible?

EDIT: I guess I'm looking for answer that's deeper than "because that's the way Java is".

Is there a particular technological reason why static methods can't be overwritten? That is, why did the designers of Java decide to make instance methods overrideable but not static methods?

EDIT: The problem with my design is I'm trying to use interfaces to enforce a coding convention.

That is, the goal of the interface is twofold:

  1. I want the IXMLizable interface to allow me to convert classes that implement it to XML elements (using polymorphism, works fine).

  2. If someone wants to make a new instance of a class that implements the IXMLizable interface, they will always know that there will be a newInstanceFromXML(Element e) static constructor.

Is there any other way to ensure this, other than just putting a comment in the interface?

+10  A: 

Because static methods cannot be overridden in subclasses, and hence they cannot be abstract. And all methods in an interface are, de facto, abstract.

Michael Myers
You could always force each type to implement any static interface methods. Typeclasses, anyone?
MichaelGG
Step outside yourself and answer the question: *Why* can't a static methods be overridden? If static methods could be overridden, what would it look like? What could you do with them? This answer is basically "You can't because you can't."
erickson
@erickson: that's why I upvoted your answer. :P
Michael Myers
Ah now you made me feel guilty ;)
erickson
Guilty? I upvoted it before you commented here, so don't feel like you were fishing for votes. :)
Michael Myers
A: 

Interfaces just provide a list of things a class will provide, not an actual implementation of those things, which is what your static item is.

If you want statics, use an abstract class and inherit it, otherwise, remove the static.

Hope that helps!

samoz
Well, in theory, you could define an interface to include a static behaviour, that is, "implementations of this interface will have a static method foo() with this signature", and leave the implementation up to the specific class. I have encountered situations where this behaviour would be useful.
Rob
+2  A: 

Well, without generics, static interfaces are useless because all static method calls are resolved at compile time. So, there's no real use for them.

With generics, they have use -- with or without a default implementation. Obviously there would need to be overriding and so on. However, my guess is that such usage wasn't very OO (as the other answers point out obtusely) and hence wasn't considered worth the effort they'd require to implement usefully.

MichaelGG
What do generics have to do with this? A static method on an interface would still be unexecutable.
DJClayworth
First, that'd be an implementation decision. But I'm guessing he doesn't want to call static methods on an interface (he could just use a class). But instead wants to have something sorta like a typeclass or whatnot over type parameters. In fact, his latest edit shows this even more clearly.
MichaelGG
+2  A: 

Interfaces are concerned with polymorphism which is inherently tied to object instances, not classes. Therefore static doesn't make sense in the context of an interface.

cliff.meyers
A: 

You can't define static methods in an interface because static methods belongs to a class not to an instance of class, and interfaces are not Classes. Read more here.

However, If you want you can do this:

public class A {
  public static void methodX() {
  }
}

public class B extends A {
  public static void methodX() {
  }
}

In this case what you have is two classes with 2 distinct static methods called methodX().

Handerson
+7  A: 

This was already asked and answered, here

To duplicate my answer:

There is never a point to declaring a static method in an interface. They cannot be executed by the normal call MyInterface.staticMethod(). If you call them by specifying the implementing class MyImplementor.staticMethod() then you must know the actual class, so it is irrelevant whether the interface contains it or not.

More importantly, static methods are never overridden, and if you try to do:

MyInterface var = new MyImplementingClass();
var.staticMethod();

the rules for static say that the method defined in the declared type of var must be executed. Since this is an interface, this is impossible.

The reason you can't execute "result=MyInterface.staticMethod()" is that it would have to execute the version of the method defined in MyInterface. But there can't be a version defined in MyInterface, because it's an interface. It doesn't have code by definition.

While you can say that this amounts to "because Java does it that way", in reality the decision is a logical consequence of other design decisions, also made for very good reason.

DJClayworth
+11  A: 
erickson
Good call on Project Coin. http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000117.html
Michael Myers
A: 

Static methods aren't virtual like instance methods so I suppose the Java designers decided they didn't want them in interfaces.

But you can put classes containing static methods inside interfaces. You could try that!

public interface Test {
    static class Inner {
        public static Object get() {
            return 0;
        }
    }
}
Adrian Pronk
A: 

I think java does not have static interface methods because you do not need them. You may think you do, but... How would you use them? If you want to call them like

MyImplClass.myMethod()

then you do not need to declare it in the interface. If you want to call them like

myInstance.myMethod()

then it should not be static. If you are actually going to use first way, but just want to enforce each implementation to have such static method, then it is really a coding convention, not a contract between instance that implements an interface and calling code.

Interfaces allow you to define contract between instance of class that implement the interface and calling code. And java helps you to be sure that this contract is not violated, so you can rely on it and don't worry what class implements this contract, just "someone who signed a contract" is enough. In case of static interfaces your code

MyImplClass.myMethod()

does not rely on the fact that each interface implementation has this method, so you do not need java to help you to be sure with it.

Pavel Feldman
+1  A: 

Several answers have discussed the problems with the concept of overridable static methods. However sometimes you come across a pattern where it seems like that's just what you want to use.

For example, I work with an object-relational layer that has value objects, but also has commands for manipulating the value objects. For various reasons, each value object class has to define some static methods that let the framework find the command instance. For example, to create a Person you'd do:

cmd = createCmd(Person.getCreateCmdId());
Person p = cmd.execute();

and to load a Person by ID you'd do

cmd = createCmd(Person.getGetCmdId());
cmd.set(ID, id);
Person p = cmd.execute();

This is fairly convenient, however it has its problems; notably the existence of the static methods can not be enforced in the interface. An overridable static method in the interface would be exactly what we'd need, if only it could work somehow.

EJBs solve this problem by having a Home interface; each object knows how to find its Home and the Home contains the "static" methods. This way the "static" methods can be overridden as needed, and you don't clutter up the normal (it's called "Remote") interface with methods that don't apply to an instance of your bean. Just make the normal interface specify a "getHome()" method. Return an instance of the Home object (which could be a singleton, I suppose) and the caller can perform operations that affect all Person objects.

Mr. Shiny and New
+1  A: 
  • "Is there a particular reason that static methods cannot be overridden".

Let me re-word that question for your by filling in the definitions.

  • "Is there a particular reason that methods resolved at compile time cannot be resolved at runtime."

Or, to put in more completely, If I want to call a method without an instance, but knowing the class, how can I have it resolved based upon the instance that I don't have.

Darron
A: 

Suppose you could do it; consider this example:

interface Iface {
  public static void thisIsTheMethod();
}

class A implements Iface {

  public static void thisIsTheMethod(){
    system.out.print("I'm class A");
  }

}

class B extends Class A {

  public static void thisIsTheMethod(){
    System.out.print("I'm class B");
  } 
}

SomeClass {

  void doStuff(Iface face) {
    IFace.thisIsTheMethod();
    // now what would/could/should happen here.
  }

}
pvgoddijn
It would print "I'm class A". However, if you typed `A.thisIsTheMethod()` it would print "I'm class B".
cdmckay
but oyr calling the methods on the interface how would you (or the compiler) know which method should be called? (rember there can be more classes dricetly implementing Iface
pvgoddijn
sorry, I meant to say: However, if you typed `B.thisIsTheMethod()` it would print "I'm class B".
cdmckay
i said IFace.thisIsTHeMethod on purpose because therein lies the problem. it would not be possible to call it on the interface without undefined behavior (even though its declared on it)
pvgoddijn
+2  A: 

Normally this is done using a Factory pattern

public interface IXMLizableFactory<T extends IXMLizable> {
  public T newInstanceFromXML(Element e);
}

public interface IXMLizable {
  public Element toXMLElement();
}
Peter Lawrey
+1 a factory pattern sounds like the solution to the problem. (though not to the question)
pvgoddijn