Why is it not possible to define an interface with static methods?

Asked

Viewed 1,170 times

13

I would like to force some of my classes to be implemented in Singleton, but I came across the following situation.

interface ICharacterSingleton{
    static Characters getInstancia();
}

public static class Zero extends Characters implements ICharacterSingleton {        
    private static Characters Instancia = null;
    private Zero(){     
        Layout.add("   111  ");
        Layout.add("  1   1 ");
        Layout.add("  1   1 ");
        Layout.add("  1   1 ");
        Layout.add("  1   1 ");
        Layout.add("  1   1 ");
        Layout.add("  1   1 ");
        Layout.add("   111  ");                         
    }

    public static Characters getInstancia() {
        if(Instancia == null)
            Instancia = new Zero();         
        return Instancia;
    }               
}

Can’t I define a static method for an interface? There is another way out of this situation?

  • 3

    It is good to note that - in Java 8 at least - you can yes have static methods on interfaces. However, you cannot use them to implement a Singleton, as well explained in the responses. Other languages (such as Python) differentiate between Static methods and class methods - the latter considering inheritance - but still it is not possible to require a derived class to give its own implementation of a class method. As Math said: "it is not possible to require by contract that a class be Singleton".

  • 1

    P.S. If it weren’t for the multiple inheritance problem, you could create a base class that keeps a record of the created instances - through a Map with this.getClass() as key - and throws an exception if more than one instance of the same class is created. Any class you inherit from it would then in fact an Singleton. This base class could even have a utility method to recover the instance - serving as a factory for these objects, and centralizing their creation and access in a standardized way. I can post this as an answer if you like, but it still doesn’t apply to the use of interfaces.

  • @utluiz I liked the idea of Singletonfactory However I will have several class inheriting from "Characters" and all of them following the same concept generating a character map forming the number in ascii, in the example above I have the class Zero, I will have One, Two and so will all inherit Characters in the case of Singletonfactory I would have to have an object factory for each class as I would manage all these instances?

6 answers

12

Methods in interfaces are implicitly public and abstract.

That is, as much as you declare a method like this in your interface:

public interface MinhaInterface {
    void teste();
}

Implicitly what you’re doing is:

public interface MinhaInterface {
    public abstract void teste();
}

Therefore, the problem is not the interface, the problem is the modifier abstract that conflicts with the modifier static. For example, you can’t do such a thing for a class either:

public abstract class MinhaClasse {
    public abstract static void teste();
}

The error is the same as trying to create a static method in an interface. The reason these two modifiers are conflicting is simple: if the method is static it means that it belongs to the class, however if it is abstract it means that it has no implementation, Oras, for what you will access a method of a class that has no implementation?

Basically:

  • static prevents you from overwriting the method, if a subclass uses the same signature of a static method, then that subclass is resetting the method and not overwriting; whereas

  • abstract requires the first concrete subclass to implement such a method, by means of the superscript.

That’s why they’re conflicting.

The solution to your case, I will give it some more thought, but at first I would say that it is not possible to compel by contract a class to be Singleton.

  • Great explanation thank you very much.

8


I turned my comment into response due to size.

The problem seems to be perfectly solved by uniting the concept of the design pattern Factory Method with the Singleton, that is, a method that manufactures a single instance of a class.

Below I will put two possible implementations...

Approach #1: a method and an attribute for each class

public abstract SingletonFactory {

    private static Zero zero = new Zero(); 
    public static Zero getInstanciaZero() {
        return zero;
    }

    private static Um um = new Um(); 
    public static Um getInstanciaUm() {
        return  um;
    }

    //...

}

Approach #2: a generic method that takes the number as a parameter

public abstract SingletonFactory {

    private static Map<Byte, ICharacterSingleton> numberMap = new HashMap<>(); 

    static {
        numberMap.put(0, new Zero());
        numberMap.put(1, new Um());
        //...
    }

    public static ICharacterSingleton getInstancia(Byte numero) {
        return numberMap.get(numero);
    }

}
  • utluiz The second approach seems to be great for me, what is the best way to encapsulate the Icharactersingleton object so that only the Singletonfactory instates it? because otherwise the object could be instantiated without the right factory? and then I would break your Singleton.

  • @Tuyoshivinicius The interface can be public, after all it is only an interface. As for the classes Zero, Um and the others, one way is to leave them in the same package as the SingletonFactory and leave their builder without the public, so that they are only visible to classes in the same package. Another way is to declare these classes within class SingletonFactory (Inner classes) with the builder private, so that only from within the class SingletonFactory it is possible to instantiate them.

  • 1

    Valew guy, your approach and the great explanation of @Math were the perfect combinations, too bad it is not possible to mark two answers as certain.

4

The interesting thing about interface is to be able to separate the implementation of the "contract" class that says what it has. That way, I can receive an object that I know implements the interface and work with it without knowing what its class is:

IEnumeravel obj = ...;
obj.BuscaEnumerador(); 

In the small example above I don’t know the obj class, it can be every one hour, it can be received as parameter. The contract is made so that I know that the object that arrives will have the method for me to call.

Static methods are called by the class, I need to know I’m working with the class Zero to call the method:

Zero.getInstancia();

2

Because it would be a contradiction of how Java does to invoke a statistical method.

A static method and independent of instances, correct? Therefore, it can be executed directly from the ". class".

Now, if Voce could have a statistical method on an interface, Java would have to look for a particular implementation of the interface in order to execute the method.

However, he might let you do something like:

public interface Coisa {
  public static int f() {
    // ...
  }
}

But Voce can’t :P

1

There are basically two types of methods: instance methods and static methods (class methods).

This concept belongs to the object-oriented paradigm, is not particular to any language.

Because static methods belong to the class, when we create a static method in a class, when starting the program in the Loader class, we check which classes have static methods. When identified a class with a static method, the implementation of this method is placed in a global scope, which can be accessed through the type that keeps the static class.

Why it is not possible to implement static methods on interfaces.

The fact that the Loader class searches an implementation to place it in a global scope, it is not allowed to place static method in interfaces, because interfaces don’t implement methods, they only keep their signatures.

Therefore, it is not possible to implement static methods in interfaces.

-2

It is not possible because an interface cannot be instantiated as a concrete class or it has no constructor method, when trying to access a static method internally class and instantiated and is ready to have direct access to that constructor method.

[]'s

  • 2

    Wrong: "It is not possible because an interface cannot be instantiated as a concrete class or it has no constructor method" - one thing has nothing to do with the other; Wrong too: "when trying to access a static method internally the class is instantiated and is ready to have direct access to that constructor method" - the class does not need to be instantiated to have a static method accessed. It is only instantiated when using the new operator. PS: interfaces can have static attributes without the slightest problem (implicitly on the interface all are static).

  • Thanks for the correction.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.