Why can't an interface have fields?
Asked Answered
P

8

7

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.

Pronucleus answered 26/8, 2015 at 0:12 Comment(0)
C
6

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.

Calash answered 26/8, 2015 at 1:51 Comment(1)
I appreciate the elaboration, and I think I get it now.Pronucleus
J
3

No, you can't sadly. Interfaces in java can only contain methods and constants. But, there is an alternative to this. Add a method like this:

String getNameTag();

See? that way, the implementations must contain a nameTag field, or they can just do some other stuff to return a string.

Also, as far as I know, you don't need to add access modifiers to interface methods.

Jeopardy answered 26/8, 2015 at 0:18 Comment(1)
IIRC, not only are access modifiers optional, using anything other than public is an error.Waine
Z
2

Interface is made for methods and constants.

You need to use abstract class as per your requirements.

public abstract class IModifier{
   public String nameTag;
   public abstract void foo();
}

Now answer to your question WHY an interface cannot require a field? Ans: Because that is the feature of abstract class. It would be almost no difference between interface and abstract class.

I hope that I answered your tricky question.

Zippy answered 26/8, 2015 at 0:31 Comment(0)
H
1

From the perspective of design: Interface defines a contract of agreed behavior which is what can be done aka methods. (E.g. int getAge() ) and less of how to do it. Then Instance Fields (int age) which are more in part what u need to achieve the behavior doesnt naturally fit. And Static final fields that are not implementation specific (E.g static final int CENTURIONAGE=100) is still availble on interface.

Then after agreeing on the contract, if you go to behavior implementation you go on to classess and abstract classes etc.

Hone answered 26/8, 2015 at 1:12 Comment(0)
A
0

No.

Interfaces can only require methods, not fields (or constructors).

You could probably achieve the same effect by putting a getter and/or setter method in the interface.

Azaleeazan answered 26/8, 2015 at 0:14 Comment(4)
Thats what i figured based on other questions I read, I was mostly looking for confirmation and seeing if someone could explain WHY it is like that.Pronucleus
"Why?" questions are always tricky. Here is some more discussion: #1514020Azaleeazan
Thats actually one I had been looking at before but all the reasons for a field having to be static final were saying that it was because you cannot instantiate the interface directly and the one comment about being able to use abstract variable in an abstract class was ignored.\Pronucleus
An abstract class is still an abstract class. It becomes part of the subclass' implementation, and it can contribute a field that way. Whereas an interface does not. My guess is that if there is a technical reason at all (as opposed to just design consideration) it might be that the resolution process of fields and methods is fundamentally different, so that field resolution cannot be done if the implementation class is not known at compile-time (which it currently is for fields, but would not be if it is in an interface). But I am just guessing.Azaleeazan
I
0

If you look up the java docs, you will get the actual statements from there.

Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods. With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.

Which should you use, abstract classes or interfaces?

Consider using abstract classes if any of these statements apply to your situation:

  1. You want to share code among several closely related classes.
  2. You expect that classes that extend your abstract class have many common methods or fields, or require access modifiers other than public (such as protected and private).
  3. You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the object to which they belong.

Consider using interfaces if any of these statements apply to your situation:

1.You expect that unrelated classes would implement your interface. For example, the interfaces Comparable and Cloneable are implemented by many unrelated classes.

2.You want to specify the behavior of a particular data type, but not concerned about who implements its behavior.

3.You want to take advantage of multiple inheritance of type.

However, based on your question first edit, you could define a field in an interface, however there is a caveat. its has to be public, static and final. In other words, define only constants ;)

public interface TimeClient {

public static final String TIME_ZONE = "Europe/Amsterdam";    //Defines a static field     

static public ZoneId getZoneId(String zoneString) {
    try {
        return ZoneId.of(zoneString);
    } catch (DateTimeException e) {
        System.err.println("Invalid time zone: " + zoneString
                + "; using default time zone instead.");
        return ZoneId.systemDefault();
    }
}

//Defines a default method
default public ZonedDateTime getZonedDateTime(String zoneString) {
    return ZonedDateTime.of(LocalDateTime.MAX, getZoneId(zoneString));
}}

The above code will compile.

Inglis answered 27/10, 2018 at 9:33 Comment(0)
R
0

Here's what I have done in many projects to be able to define an "interface" that defines not fields but a "contract" for fields.

The suggestion made earlier in this topic to use abstract base classes has a severe limitation. A concrete class can implement multiple interfaces in Java's limited form of multiple inheritance, but... it can only extend one base class. That means that the base class method only works for one interface that requires a contract for fields.

In the way of a use case, suppose I wanted a contract/interface for several kinds of domain objects:

  • Objects with an expiration date
  • Objects with audit trails (created by, created dated,....)

I may have objects which can expire but don't need audit trails. I may have other objects which are the opposite: they need audit trails, but don't have expiration dates.

Base classes don't allow for a sorta "pick and choose" among these. Any base class would have to define both, or you'd have to have base classes for ALL combinations.

Here's my solution and it has worked quite well: I define the setters and getters as abstract methods in the interface. You leave the implementation to the concrete classes.

public interface Auditable<USER_TYPE> {
    Instant getCreatedOn();
    void setCreatedOn(Instant)

    USER_TYPE getCreatedBy();
    void setCreatedBy(USER_TYPE creator);

A concrete class that is both Audtiable (using String to identify a user) and Expirable would look like this (I'm using Lombok)

@Getter @Setter
public AuditableExpirableObject implement Auditable<String>, Expirable {
    private String createdBy
    private Instant createdOn;
    private Instant expirationDate;

This allows concrete objects to select which interfaces they use. You do have to DEFINE the fields, but it is often a "good thing" to define them in concrete types but implement the contract of an inteface. An example of why, would be to allow each concrete class to determine things like:

  • The data type (as in the user type for Auditable)
  • Annotations for persistence or serialization (Hibernate, JPA, Jackson, Gson, etc.)
  • Custom initializations or protection levels
Rotten answered 22/2, 2021 at 18:26 Comment(0)
P
0

After some experiments I think I got the point. I noticed that Interface is just like inheritance, a "contract" which shows the ability to do something to fit in polymorphism. Interface doesn't implement methods but only leave abstract declarations to avoid some multi-inheritance problems and complexities such as "diamonds problem". If Interface allows non-static field then diamonds problem would appear again. And by the way, all the demands for non-static fields can always be achieved in the methods implementation for example getter and setter.

Pitiful answered 4/6, 2024 at 12:11 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.