Java Interface Usage Guidelines -- Are getters and setters in an interface bad?

What do people think of the best guidelines to use in an interface? What should and shouldn't go into an interface?

I've heard people say that, as a general rule, an interface must only define behavior and not state. Does this mean that an interface shouldn't contain getters and setters?

My opinion: Maybe not so for setters, but sometimes I think that getters are valid to be placed in an interface. This is merely to enforce the implementation classes to implement those getters and so to indicate that the clients are able to call those getters to check on something, for example.

Answers


I think that there are two types of interfaces declared in general:

  1. a service description. This might be something like CalculationService. I don't think that methods getX should be in this sort of interface, and certainly not setX. They quite clearly imply implementation detail, which is not the job of this type of interface.
  2. a data model - exists solely to abstract out the implementation of data objects in the system. These might be used to aid in testing or just because some people as old as me remember the days when (for example) using a persistence framework tied you down to having a particular superclasss (i.e. you would choose to implement an interface in case you switched your persistence layer). I think that having JavaBean methods in this type of interface is entirely reasonable.

Note: the collections classes probably fit in to type #2


I don't see why an interface can't define getters and setters. For instance, List.size() is effectively a getter. The interface must define the behaviour rather than the implementation though - it can't say how you'll handle the state, but it can insist that you can get it and set it.

Collection interfaces are all about state, for example - but different collections can store that state in radically different ways.

EDIT: The comments suggest that getters and setters imply a simple field is used for backing storage. I vehemently disagree with this implication. To my mind there's an implication that it's "reasonably cheap" to get/set the value, but not that it's stored as a field with a trivial implementation.


EDIT: As noted in the comments, this is made explicit in the JavaBeans specification section 7.1:

Thus even when a script writer types in something such as b.Label = foo there is still a method call into the target object to set the property, and the target object has full programmatic control.

So properties need not just be simple data fields, they can actually be computed values. Updates may have various programmatic side effects. For example, changing a bean’s background color property might also cause the bean to be repainted with the new color."


If the supposed implication were true, we might just as well expose properties as fields directly. Fortunately that implication doesn't hold: getters and setters are perfectly within their rights to compute things.

For example, consider a component with

getWidth()
getHeight()
getSize()

Do you believe there's an implication that there are three variables there? Would it not be reasonable to either have:

private int width;
private int height;

public int getWidth() {
    return width;
}

public int getHeight() {
    return height;
}

public Size getSize() {
    return new Size(width, height); // Assuming an immutable Size type
}

Or (preferrably IMO):

private Size size;

public int getWidth() {
    return size.getWidth();
}

public int getHeight() {
    return size.getHeight();
}

public Size getSize() {
    return size;
}

Here either the size property or the height/width properties are for convenience only - but I don't see that that makes them invalid in any way.


There's nothing inherently evil about getters/setters. However:

  1. I tend to make my objects immutable (in the first instance) with respect to the fields they contain. Why ? I instantiate most things during the construction phase. If I want to change something later then I relax those restrictions. So my interfaces will tend to contain getters, but not setters (there are other benefits - particularly threading).
  2. I want my objects to do things for me, not the other way around. So when one of my objects acquires a number of getters, I start to ask whether that object should have more functionality in it, rather than exposing all its data for something else to work with. See this answer for more detail.

These are all guidelines, note.


I don't think a bean should have an interface on top of it, in general. A javabean is an interface in the more general meaning. An Interface specifies the external contract of something more complex. A javabean's external contract and its internal representation are identical.

I wouldn't say that you shouldn't have getters in an interface, though. It makes perfect sense to have a ReadableDataThingie interface that is implemented by DataThingieBean.


I've heard people say that, as a general rule, an interface must only define behavior and not state. Does this mean that an interface shouldn't contain getters and setters?

For starters, at least with Java and excluding Exception declarations, you cannot define complete behavior without state. In Java, interfaces do not define behavior. They can't. What they define are types; promises of implementing a set of feature signatures possibly with some post-conditions wrt exceptions. But that's it. Behavior and state are defined by classes implementing those interfaces.

Secondly, if getters and setters are defined in an interface, they don't really define complete behavior (other that one is for read and one is for write wrt a property.) You can have complex behavior behind setters and getters, but they can only be implemented in the actual classes. There is nothing in the Java language that can allow us to freely define behavior in interfaces except for the most restrictive of cases.

With that into consideration, there is nothing wrong - syntactically and semantically - with having setters and getters in interfaces.

If your application is well-modeled and the problem requires that you have an interface defining setters and getters, why not. For example, take a look at the ServletResponse interface.

Now, if we look at getters and setters from the point of view of implementing classes compliant with the JavaBeans specs, then you do not need to define interfaces for them.

But if you have things that require setters and getters, like a bean might, and which is also required to be plugged at compile-type (not at run-time like a bean might), and for which multiple implementations might exist, then yeah, this would call for an interface defining getters and setters.

Hope it helps.


This touches upon the whole Getter/Setters are evil topic which is addressed multiple times on this site and elsewhere.

I tend to favour not having accessors in the interface, but to add collaborators using constructor arguments to the implementation.


The fact that the straightforward implementation of something is as a getter shouldn't stop it being in an interface if it needs to be.


For further reading: Practical API Design Confessions of a Java Framework Architect (Jaroslav Tulach, 2008, Apress).


I used those kind of interfaces, for example we had classes with fields beginDate, endDate. Those fields were in many classes and I had one use case I need to get those dates for different objects, so I extracted interface and was very happy :)


Basically if the answer to "Do I need to know the value of [state, property, whateverThignAMaGit] in order to work with an instance of it ?" then yes... the accessors belong in the interface.

List.size() from John above is a perfect example of a getter that needs to be defined in an interface


Getters are used to query the state of an object - which you can really avoid when designing your interface. Read http://www.pragprog.com/articles/tell-dont-ask


Need Your Help

How to research unmanaged memory leaks in .NET?

c# sql-server wcf memory-leaks msmq

I have a WCF service running over MSMQ. Memory gradually increases over time, indicating that there is some sort of memory leak. I ran the service locally and monitored some counters using PerfMo...

Rails association with multiple foreign keys

ruby-on-rails ruby-on-rails-4 associations model-associations

I want to be able to use two columns on one table to define a relationship. So using a task app as an example.