Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are getters and setters poor design? Contradictory advice seen [duplicate]

People also ask

Are getters and setters bad design?

Getter and setter methods (also known as accessors) are dangerous for the same reason that public fields are dangerous: They provide external access to implementation details. What if you need to change the accessed field's type? You also have to change the accessor's return type.

What is the advantage of using getter and setter?

The getter and setter method gives you centralized control of how a certain field is initialized and provided to the client, which makes it much easier to verify and debug. To see which thread is accessing and what values are going out, you can easily place breakpoints or a print statement.

Are getters and setters good practice?

It is good programming practice not to use getters and setters in classes that are intended to be more than bundles of data (like a C struct ). They expose the internal structure of the class, violating encapsulation and greatly increasing coupling.

Do getters and setters enforce or weaken encapsulation?

Having getters and setters does not in itself break encapsulation.


There is also the point of view that most of the time, using setters still breaks encapsulation by allowing you to set values that are meaningless. As a very obvious example, if you have a score counter on the game that only ever goes up, instead of

// Game
private int score;
public void setScore(int score) { this.score = score; }
public int getScore() { return score; }
// Usage
game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);

it should be

// Game
private int score;
public int getScore() { return score; }
public void addScore(int delta) { score += delta; }
// Usage
game.addScore(ENEMY_DESTROYED_SCORE);

This is perhaps a bit of a facile example. What I'm trying to say is that discussing getter/setters vs public fields often obscures bigger problems with objects manipulating each others' internal state in an intimate manner and hence being too closely coupled.

The idea is to make methods that directly do things you want to do. An example would be how to set enemies' "alive" status. You might be tempted to have a setAlive(boolean alive) method. Instead you should have:

private boolean alive = true;
public boolean isAlive() { return alive; }
public void kill() { alive = false; }

The reason for this is that if you change the implementation that things no longer have an "alive" boolean but rather a "hit points" value, you can change that around without breaking the contract of the two methods you wrote earlier:

private int hp; // Set in constructor.
public boolean isAlive() { return hp > 0; } // Same method signature.
public void kill() { hp = 0; } // Same method signature.
public void damage(int damage) { hp -= damage; }

  • Very evil: public fields.
  • Somewhat evil: Getters and setters where they're not required.
  • Good: Getters and setters only where they're really required - make the type expose "larger" behaviour which happens to use its state, rather than just treating the type as a repository of state to be manipulated by other types.

It really depends on the situation though - sometimes you really do just want a dumb data object.


You've already had a lot of good answers on this, so I'll just give my two cents. Getters and setters are very, very evil. They essentially let you pretend to hide your object's internals when most of the time all you've done is tossed in redundant code that does nothing to hide internal state. For a simple POJO, there's no reason why getName() and setName() can't be replaced with obj.name = "Tom".

If the method call merely replaces assignment, then all you've gained by preferring the method call is code bloat. Unfortunately, the language has enshrined the use of getters and setters in the JavaBeans specification, so Java programmers are forced to use them, even when doing so makes no sense whatsoever.

Fortunately, Eclipse (and probably other IDEs as well) lets you automatically generate them. And for a fun project, I once built a code-generator for them in XSLT. But if there's one thing I'd get rid of in Java, its the over-dependence on getters and setters.


Getters and setters enforce the concept of encapsulation in object-oriented programming.

By having the states of the object hidden from the outside world, the object is truly in charge of itself, and cannot be altered in ways that aren't intended. The only ways the object can be manipulated are through exposed public methods, such as getters and setters.

There are a few advantages for having getters and setters:

1. Allowing future changes without modification to code that uses the modified class.

One of the big advantage of using a getter and setter is that once the public methods are defined and there comes a time when the underlying implementation needs to be changed (e.g. finding a bug that needs to be fixed, using a different algorithm for improving performance, etc.), by having the getters and setters be the only way to manipulate the object, it will allow existing code to not break, and work as expected even after the change.

For example, let's say there's a setValue method which sets the value private variable in an object:

public void setValue(int value)
{
    this.value = value;
}

But then, there was a new requirement which needed to keep track of the number of times value was changed. With the setter in place, the change is fairly trivial:

public void setValue(int value)
{
    this.value = value;
    count++;
}

If the value field were public, there is no easy way to come back later and add a counter that keeps track of the number of times the value was changed. Therefore, having getters and setters are one way to "future-proof" the class for changes which may come later.

2. Enforcing the means by which the object can be manipulated.

Another way getters and setters come in handy is to enforce the ways the object can be manipulated, therefore, the object is in control of its own state. With public variables of an object exposed, it can easily be corrupted.

For example, an ImmutableArray object contains an int array called myArray. If the array were a public field, it just won't be immutable:

ImmutableArray a = new ImmutableArray();
int[] b = a.myArray;
b[0] = 10;      // Oops, the ImmutableArray a's contents have been changed.

To implement a truly immutable array, a getter for the array (getArray method) should be written so it returns a copy of its array:

public int[] getArray()
{
    return myArray.clone();
}

And even if the following occurs:

ImmutableArray a = new ImmutableArray();
int[] b = a.getArray();
b[0] = 10;      // No problem, only the copy of the array is affected.

The ImmutableArray is indeed immutable. Exposing the variables of an object will allow it to be manipulated in ways which aren't intended, but only exposing certain ways (getters and setters), the object can be manipulated in intended ways.

I suppose having getters and setters would be more important for classes which are part of an API that is going to be used by others, as it allows keeping the API intact and unchanged while allowing changes in the underlying implementation.

With all the advantages of getters and setters said, if the getter is merely returning the value of the private variable and the setter is merely accepting a value and assigning it to a private variable, it seems the getters and setter are just extraneous and really a waste. If the class is going to be just for internal use by an application that is not going to be used by others, using getters and setters extensively may not be as important as when writing a public API.


They absolutely are evil.

@coobird unfortunately they absolutely do not "enforce the concept of encapsulation", all they do is make you think you're encapsulating data when in fact you're exposing data via a property with delusions of method grandeur. Anything a getter/setter does a public field does better.

First, if you want public data, make it public, get rid of the getter & setter methods to reduce the number of methods the client has to wade through and make it cognitively simpler for the client to change it's value by eg.

object.field = value;

instead of the more cognitively intense

object.setField(value);

where the client must now check the getter/setter method to see if it has any side-effects.

Second, if you really need to do something else in the method, why call it a get/set method when it's got more responsibilities than simply getting or setting? Either follow the SRP or call the method something that actually tells you what the whole method does like Zarkonnen's examples he mentioned eg.

public void kill(){
    isAlive = false;
    removeFromWorld(this);
}

instead of

public void setAlive(boolean isAlive){
    this.isAlive = isAlive;
    if (isAlive)
        addToWorld(this);
    else
        removeFromWorld(this);
}

where does the setAlive(boolean) method tell the client that as a side-effect it'll remove the object from the world? Why should the client have any knowledge about the isAlive field? Plus what happens when the object is re-added to the world, should it be re-initialised? why would the client care about any of that?

IMHO the moral is to name methods to say exactly what they do, follow the SRP and get rid of getters/setters. If there's problems without getters/setters, tell objects to do their own dirty work inside their own class instead of trying to do things with them in other classes.

here endeth my rant, sorry about that ;)