Reputation: 352
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.
Upvotes: 7
Views: 12771
Reputation: 1
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.
Upvotes: 0
Reputation: 968
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:
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:
Auditable
)Upvotes: 0
Reputation: 947
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:
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.
Upvotes: 0
Reputation: 158
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.
Upvotes: 6
Reputation: 76
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.
Upvotes: 1
Reputation: 1912
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.
Upvotes: 2
Reputation: 274730
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.
Upvotes: 3
Reputation: 262842
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.
Upvotes: 0