javainterface

Why can't an interface have fields?


I have a class SpecificModifier implements IModifier and there are many very similar class that also implement IModifier. I want every class that implements IModifier to have a public String nameTag.

I am trying to do something like this:

public interface IModifier{
   public String nameTag;
   public void foo();
}

But Java doesn't allow interface to contain a field. Why is that? What to do in my case?

My understand of the purpose of abstract classes vs interfaces. An interface is used purely to declare necessary parts of whatever implements it, so that all the objects have common parts that can be referenced. While an abstract class is used to provide common functionality to multiple classes.

That is a little bit of an over simplification but regardless, I still see no reason, other than an oversight by the language designers, that an interface cannot have an abstract field.


Solution

  • An Interface specifies a contract, which a concrete class that implements the Interface must adhere to. This contract describes how an implementation should act. In the Interface specification, there should be clear comments that describe what the purpose of each method is. The use of an Interface decouples the contract from the actual implementation. Fields are an implementation detail, as fields do not describe how a class should "act as."

    For instance, Interfaces are commonly used as a declared type and a concrete implementation is used as an actual type.

        Map<Key,Value> m = new HashMap<>();
    

    Consider the java.util.Map Interface for a moment. It describes how a Map should act, via its set of methods. There are several different implementations of the Map interface that allow users to choose the correct implementation for their needs.

    Specifying that a field must be used by several sub classes implies that there is some semblance of a class hierarchy. In this case an abstract class could do the trick.

       abstract class IModParent implements IModifier{
          protected String nameTag;
       }
    

    Now you can have a concrete class.

       class SpecificModifier extends IModParent{
    
          SpecificModifier(String nameTag){ this.nameTag = nameTag; }
    
          @Override
          public void foo(){ System.out.println(nameTag); }
       }
    

    And a declaration.

        IModifier imod = new SpecificModifier("MyName");
    

    This gives you the flexibility of using an Interface type while still being able to share implementation details via a non-instantiable abstract class across the group of concrete classes that you want.