Where I work I see lots of classes that do things like this:
public class ClassThatCallsItsOwnGettersAndSetters {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
setField("value");
//do stuff
String localField = getField();
//do stuff with "localField"
}
}
If I wrote this from scratch, I would have written the methodWithLogic()
like this instead:
public class ClassThatUsesItsOwnFields {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
field = "value";
//do stuff
//do stuff with "field"
}
}
I feel that when the class calls its own getters and setters, it makes the code harder to read. To me it almost implies that complex logic is happening in that method call even though in our case it almost never is. When I’m debugging some unfamiliar code, who’s to say that the bug isn’t some side effect in that method? In other words, it makes me take lots of side trips on the journey of understanding the code.
Are there benefits to the first method? Is the first method actually better?
2
I won’t say which is better or worse, because that partly depends on your situation (in my opinion). But consider that your getters and setters may change implementation later, and bypassing them would skip that logic.
For example, what happens if you add a “dirty” flag to some setter fields later? By calling your setters in your internal code you’ll set the dirty flag without changing any other code. In many situations this would be a good thing.
3
Calling the setter directly is not, in and of itself, a problem. The question really should be: Why does our code have setters everywhere?
Mutable classes are a dangerous game, particularly where the class itself manages its own state. Consider how many of those setters truly need to exist. How many could be set in the constructor and then become encapsulated entirely by the class itself?
If the field must be settable externally then ask yourself if the method with logic should be there. Is your class itself really just a data/state class? Does this class have more than one responsibility?
Don’t get me wrong, there will be cases where this is fine. I’m not saying that you should eliminate setters on classes with logic entirely. But these should be the exception, not the rule. And, in those few cases, it should be obvious which to access directly.
2
Yes, the methods of your class should call the getters and setters. The whole point in writing getters and setters is future proofing. You could make every property a field and directly expose the data to the users of the class. The reason you build the getters and setters isn’t necessarily because there is complex logic now but so that the interface doesn’t break in the future if you have to add it.
3
To answer your questions in one word, yes.
Having a class call its own getters and setters adds extensibility and provides a better base for future code.
Say you have something like this:
public class Vehicle
{
private int year;
private String make;
public Vehicle(int year, String make)
{
setYear(year);
setMake(make);
}
public void setYear(int year)
{
this.year = year;
}
public void setMake(String make)
{
this.make = make;
}
}
Calling the setters for year and make currently may not add any functionality, but what if you wanted to add something like input validation to the setters?
public class Vehicle
{
private int year;
private String make;
public Vehicle(int year, String make)
{
setYear(year);
setMake(make);
}
public void setYear(int year)
{
if(year > 0)
{
this.year = year;
}
else
{
System.out.println(year + " is not a valid year!");
}
}
public void setMake(String make)
{
this.make = make;
}
}
One thing that hasn’t been mentioned is that getter and setters (as all methods) are virtual in Java. This adds another feature to always using them in your code. Another user could extend your class, overwriting your getters and setters. Your base class would then be using the subclass’s data instead of its own. In a language where you explicitly mark virtual functions, this is much more handy since you can predict and declare which functions this can be done with. In Java, this is something you would always have to be aware of. If it is desired behavior then using them in your code is a good thing, otherwise not so much.
If you are trying to accomplish something that is provided by the public interface, then use the getters/setters.
However, as the owner/developer of the class, you are allowed to access the private sections of your code (from within the class of course), but you are also responsible for mitigating the dangers.
So maybe you have a getter that iterates over some internal list, and you want to get the current value without incrementing the iterator. In this case, use the private variable.
public class MyClass
{
private int i;
private List<string> list;
public string getNextString()
{
i++;
return list[i];
}
private void getString()
{
// Do not increment
string currentString = list[i];
// Increment
string nextString = getNextString();
}
}
1
Yes. Getters and setters represent state, so turn this question around — do you want to have to keep track of multiple ways of changing an objects state in the same manner unless you have to?
The fewer things you have to keep track of the better — this is why immutable objects are easier to deal with.
Consider, there is nothing preventing you from having both a public field and a public getter/setter — but what would you gain?
It may on occassion be desirable or even necessary to directly access the field for one or more reasons, you shouldn’t shy away from that if it happens. But you should really only do it if there is a defined benefit to doing so.
3
Both methods have their use cases. As public setter keeps field value (and/or bound values) consistent, you should use setter when your method logic does not interfere with this consistency logic. If you just set your “property”, use setter. On the other hand, there are situations, where you need direct access to some fields, for example bulk operations with heavy setter, or operations where setter concept is too simple.
It is your responsibility to keep things consistent. Setter does this by definition, but cannot cover complex cases.
I would say No..
If your getters/setters just get and set (no lazy initialization, no checks, etc) then just use your variables. If in the future you change your getters/setters, you can very well change your methodWithLogic()
(because its your class that’s changing) and you can call a getter/setter instead of direct assignment. You can document this call for the getter/setter (as it will be strange to call a getter/setter when the rest of your class code is directly using the variable).
The JVM will inline frequent calls to getters/setters. So, its never a performance issue. The gain of using variables is readability and IMHO, I would go for it.
Hope this helps..