This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
This is a question about programming style. Everyone knows that encapsulating your variables is a Good Thing (TM). Obviously one class wants to access another class's private variables, it must do so via getter/setter methods.
My question is this: When a class wants to access its own private variables, should it do so via getter/setter methods or directly?
On the one hand, going via the getter/setter methods ensures that, if there's any special processing going on within the getter/setter method, you aren't bypassing it.
On the other hand, I can't help feeling that using getter/setter methods when no such special processing is going on tends to clutter up the code.
I could be convinced either way. What is generally considered the Right Way (TM) to access private variables?
I'd say there really is not one generally accepted way to do this. Your arguments for both sides are valid, and different people, and different situations, will cause the balance to tip one way or another.
One thing that more and more people have come to accept: the overuse of getters and especially setters is a bad thing. The only sort of class that should always have them is a "dumb data" sort of class, a JavaBean or DTO. It's much better to ask a class "please take these inputs and compute something for me and return the results" than it is to say "please give me your innards and I will fiddle with them."
If a pizza guy came to your house, and he said "please turn around so I can take the money you owe me out of your wallet", would you cooperate? No. You want the pizza guy to ask you to pay a given amount for the pizza, whereupon you will do so.
Objects are the same way. They don't want you to call setCashOnHand(getCashOnHand() - 19.95). They want you to call payCheck(19.95).
I agree with most of EFH's points, though I think the pizza guy metaphor is a little off, as it relates more to how class A should interact with class B, and Wally's question was more about how A should interact with its osn private data. Though EFH's point was more directed at why getters and setters are generally a bad idea, which I agree with.
Anyway, to address Wally's question from my own point of view: even if we assume that there may be a valid reason to have a getter or setter in a class, I would not expect a class to use the getter or setter to access its own private data. First, if the getter/setter has no side effects, it doesn't much matter whether you access the data through the getter/setter or directly, except that the getter/setter may be a tiny bit slower and a tiny bit longer to write. If the getter/setter does have side effects, then it's not really behaving as most other programmers would expect for a method whose name begins with get or set, and so there's a certain danger you're misleading other programmers by calling it a getter/setter.
More importantly, if we assume that there's some side effect that really is important which we want to occur, e.g. send an e-mail to the accounting department any time variable x changes - expecting developers to always use the setter even when they could access the variable directly is usually error-prone. You may well get a situation where most of the developers remember to do this most of the time, but occasionally someone forgets, or thinks they have a good reason to violate the rule. And then things can get more dangerous, because most other developers think the the e-mail is being sent whenever a change occurs, but there is actually an exception to this rule somewhere, and it's not obvious to anyone.
I would say that if you have a situation where you need to ensure that some side effect occurs whenever variable x changes, you really should take the extra precaution of putting x in a separate class whose purpose is to isolate x from the class that is trying to access it, to ensure that the access only occurs through the setter. If the side effect is really important, don't rely on coders to simply remember that they should use the setter - enforce it.
Alternately, there are probably some other ways to automatically check that access is performed only through the setter. Some code analysis tools can probably perform this check for you. If you can set up an automated build process such that you can reliably check to see that so one is accessing a variable directly (except the setter method itself, of course) then it may make sense to require developers to always use the setter. I've never worked on a project like this, and it seems a bit alien to me, but I suppose it's possible this might work.
Of course if you're using a language other than Java, there may be other options. Some languages do allow you to reliably enforce side effects when a variable is changed, or even when it's viewed. But within Java, I would generally recommend against this practice.
If the variable has a getter method, and it is not declared final, then the class itself should generally use the getter method rather than accessing the variable directly. (I would make an exception for methods such as equals() and compareTo(), though.)
I say this after having bad experiences trying to subclass Swing classes that provide non-final getter methods; when I wrote subclasses that overrode the getSomething() method, my version of the method wasn't called when it should have been because the base class was accessing its internal data directly.
Joined: Jan 30, 2000
Good point. I'd agree with that, in that I would prefer to make the method or class final, or take extra measures to allow people to override successfully. For me this falls under "Design and document for inheritance or else prohibit it", Item 15 from Joshua Bloch's Effective Java. Some people may express similar concepts in more absolutist terms,but whatever. If the superclass is outside your control and does not obey this principle, overriding can be difficult indeed. Consider: what if the superclass was also accessing this "something" field? Do you know whether it used getSomething() or accessed this.something directly? What if it did both? In the situation you describe, there are potential headaches with overriding getSomething() either way. I would advocate not overriding that getter if you can possible help it; if that's not possible, I don't think there's really a single solution. You've just got to try to navigate the particular mess the base class programmer(s) left for you, as best you can. Not an uncommon occurrance with Swing in particular, I think. [ July 28, 2006: Message edited by: Jim Yingst ]