An interface in Java does not have member fields, only methods. (Discussed here.) In other words, an interface defines behavior, but not state.
You can imply a property exists by having JavaBeans-style accessor methods get…
& set…
declared on your interface.
If you want to ensure each object has its own member field of a certain type with a certain name, then yes, as you suggested, define an abstract class with that field.
Of course you can do both of these: write an abstract class holding the member field that implements the interface requiring the accessor methods. Whether doing both is a good idea or not depends on your specific scenario.
The following is one possible example scenario for having both (a) an abstract class carrying a member field, along with (b) an interface requiring getter/setter accessor methods. I am not entirely sure of the integrity of my logic in this example, but hopefully it conveys the general idea.
Vehicles come in all sorts. Some are legal to use on the public streets, and some are not. One aspect of being street-legal is having a Vehicle identification number (VIN).
Let's define a hierarchy of vehicles.
Vehicle
is the grandparent superclass, and is abstract.
GoKart
is one child subclass of Vehicle
, also abstract, and not legal to drive on streets.
Vin
is a record representing our Vehicle identification number (VIN) type.
Car
is another child subclass of Vehicle
, also abstract. But a car is legal to drive on the street. This abstract class carries a protected
class member of type Vin
, inherited by any subclasses.
- To mark the
Car
class and its subclasses as being street legal, we define a StreetLegal
interface. That interface defines a pair of methods to imply that a property Vin
exists on all classes implementing this method.
- To pull this all together, we have one example concrete class
HondaElement
for a particular kind of car.
package work.basil.example.cartalk;
public abstract class Vehicle
{
}
package work.basil.example.cartalk;
// Not street-legal.
// https://en.wikipedia.org/wiki/Go-kart
public abstract class GoKart extends Vehicle
{
public boolean hasRemoteSpeedControl ;
}
package work.basil.example.cartalk;
// VIN = Vehicle identification number.
// https://en.wikipedia.org/wiki/Vehicle_identification_number#North_American_check_digits
public record Vin(String countryCode, int checkDigit, String serialNumber)
{
// Add constructor to validate data.
}
package work.basil.example.cartalk;
public abstract class Car extends Vehicle implements StreetLegal
{
protected Vin vin ;
}
package work.basil.example.cartalk;
public interface StreetLegal
{
public Vin getVin ( );
public void setVin ( Vin vin );
}
package work.basil.example.cartalk;
public class HondaElement extends Car implements StreetLegal
{
public HondaElement ( Vin vin )
{
this.vin = vin; // Accessing member field defined on abstract superclass `Car`.
}
@Override
public Vin getVin ( )
{
return this.vin; // Accessing member field defined on abstract superclass `Car`.
}
@Override
public void setVin ( Vin vin )
{
this.vin = vin; // Accessing member field defined on abstract superclass `Car`.
}
}