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

His picture His · Jul 15, 2009 · Viewed 32.7k times · Source

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.

Answer

Jon Skeet picture Jon Skeet · Jul 15, 2009

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.