Java Forum / General / May 2006
Accessor Methods
fightingbull06 - 18 May 2006 10:38 GMT Am a newbie to Java Programming and am studying Accessor Methods. If you designate variables as "private", then you can change their values using "accessor methods". So what's the point of making them "private" if you can still manipulate them using accessor methods.
Thomas Weidenfeller - 18 May 2006 10:44 GMT > Am a newbie to Java Programming you might consider asking newbie questions in comp.lang.java.help
> If you designate variables as "private", then you can change their > values using "accessor methods". So what's the point of making them > "private" if you can still manipulate them using accessor methods. - More control and flexibility (the methods can check value ranges, can ensure consistency with other values, can create a value on the fly, etc.)
- Hiding of the actual data type used to store the variable
- Methods can be overridden in subclasses
etc.
/Thomas
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Patricia Shanahan - 18 May 2006 11:44 GMT > Am a newbie to Java Programming and am studying Accessor Methods. > If you designate variables as "private", then you can change their > values using "accessor methods". So what's the point of making them > "private" if you can still manipulate them using accessor methods. Unthinkingly creating public accessor methods for all private fields would indeed destroy the point of making the field private.
An accessor method should operate on some externally visible/settable attribute of the object. If that attribute happens to be directly represented by a simple private field, the accessor methods will have very simple implementations.
If a private field is just part of the implementation, it should not have accessor methods at all.
In some cases, a field represents a public attribute, but other actions are needed to keep data structures consistent when it changes. Or there are conditions on when and how the field can change. For example, it might have a limited range.
Even if, initially, a private field just represents some public attribute, and its accessor methods are trivial, using accessor methods keeps options open, for both the class and its subclasses.
Patricia
mike - 18 May 2006 15:12 GMT I believe that a lot of it has to do with style too. It is a good practice to not allow access to all your variables, then provide accessor methods that make them changeable. This also provides consistancy in the code. Also a huge reason to do it, is to verify data that is being put in. e.g. If I have a variable in a class called age, I know that someone's age should never be negative and (depending on what I am doing) should probably never be over about 150. So, if I ask them for their age, I can store it using the accessor method and if it is outside of the range, I can throw an exception.
Another reason for making variables private, is for values that you want the program to be able to access, but not change. Then you can provide a "getter" method that returns the value.
dimitar - 18 May 2006 16:30 GMT I would say that if possible, you should avoid providing access to your class internals. Think about what you want to do with these values?
Many times you want to perform some calculation of a sort and write the data back in the same class. This might be better off as a method of this class which takes the external data as arguments.
Sometimes, you need to pass the value to another class. This might be a place for the visitor pattern.
If you want to poll the data and if it matches certain conditions do something, you might want to consider using listeners (with or without event object).
A few good reasons to use accessors: - you want to provide read-only access to primitive fields. - you want to return a view of complex object (i.e. Collections.unmodifiableXXX(), Collections.checkedXXX()) - you want to provide write-only access for dependency-injection style configuration. - you want to validate the value before you set it and throw exception or return status code if it's not legal. - you want to keep internal consistency (e.g. invalidate cached derived value) - if you use bean introspection (or use a library that does) - if you want binary compatibility. Making field private after the fact and changing the access to accessor methods would break all 3rd-party code which use your class.
The paragraph that follows is somewhat controversial. I've taken this approach in my latest desktop app and so far it works fine, but I'd like to hear if somebody can think of potential issues.
Sometimes what you need is really a data structure and not a class. In this case - just use one, make a class with all public fields and don't worry about flexibility. Every modern IDE supports refactorings, which make it quite easy to replace field access with accessor invocation. This makes the code less cluttered and I would say more 'semantic'.
cheers, Dimitar
Alex Whitney - 18 May 2006 17:10 GMT Yeah, it seems pointless to make a simple accessor/mutator for a private variable, but there are many situations (as people have already pointed out) where you might want to check the data that is being entered. Plus, the "point" of creating simple accessor methods isn't just to validate data, but it also reinforces that idea of encapsulation. Allowing the object to handle how data is validated makes the code much more portable. It's the whole idea of encapsulation - the user of the object shouldn't have to know (or even be allowed to know) what is going on inside the object. It is just another one of those good coding practices.
dimitar - 18 May 2006 23:26 GMT I really can't see how this:
class Credentials { final String user; final String pass; User(String u, String p) { user=u; pass=p; } }
is less encapsulated than:
class Credentials { private final String user; private final String pass; User(String u, String p) { user=u; pass=p; } String getUser() { return user; } String getPass() { return pass; } }
If this is a package private class, this usually means that one controls all clients and a refactoring would fix all dependents.
If we go along this lines, IMHO declarative aspects communicate the validation intentions in a cleaner way than the getters which might be miles away from the actual variable. See example:
class Credentials { @OnSet("if (newValue==null) throw new IllegalArgumentException()") final String user;
@OnSet("checkPassword(newValue)") final String pass;
User(String u, String p) { user=u; pass=p; } private checkPassword { ... } }
any thoughts?
Dale King - 19 May 2006 15:29 GMT > I really can't see how this: > [quoted text clipped - 13 lines] > String getPass() { return pass; } > } In Java it is less encapsulated. You are tying users of the class to the fact that the value is a field of the class. If that needs to change later (e.g. the values are not stored but computed or gotten from somewhere else or perhaps you need to do a security check before returning the password) then you will have to switch to accessors which requires changing all users of the class.
In C#, that is not as much of an issue because the same syntax can be used by clients to interact with exposed fields or for properties.
 Signature Dale King
Thomas Hawtin - 19 May 2006 15:36 GMT > In Java it is less encapsulated. You are tying users of the class to the > fact that the value is a field of the class. If that needs to change > later (e.g. the values are not stored but computed or gotten from > somewhere else or perhaps you need to do a security check before > returning the password) then you will have to switch to accessors which > requires changing all users of the class. Can modern IDEs not do this sort of thing as a single operation?
> In C#, that is not as much of an issue because the same syntax can be > used by clients to interact with exposed fields or for properties. As I understand it users of the class would still have to be recompiled.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Dale King - 19 May 2006 20:08 GMT >> In Java it is less encapsulated. You are tying users of the class to >> the fact that the value is a field of the class. If that needs to [quoted text clipped - 4 lines] > > Can modern IDEs not do this sort of thing as a single operation? That logic has a faulty, hidden assumption. You are assuming that the owner of the code being called owns all code that calls it. In the case of a public API being used by others you don't have access to the calling code. Some calling code may not even be written yet when you change the code.
That's a point I make in discussions about the YAGNI principle in extreme programming which assumes the cost of change is constant over time. In the case of public API's this is definitely not true.
>> In C#, that is not as much of an issue because the same syntax can be >> used by clients to interact with exposed fields or for properties. > > As I understand it users of the class would still have to be recompiled. Don't know about that.
 Signature Dale King
Oliver Wong - 19 May 2006 21:30 GMT >>> In Java it is less encapsulated. You are tying users of the class to the >>> fact that the value is a field of the class. If that needs to change [quoted text clipped - 14 lines] > programming which assumes the cost of change is constant over time. In the > case of public API's this is definitely not true. Another example where this is a pain:
We're using JavaCC which is a parser generator (i.e. as part of its output, it emits Java source code). Here's one of the classes that the generated code manipulates:
<code> class Node { /*various public fields*/ public Node nextNode; public Node childNode; } </code>
As you can see, it's a tree hierarchy with sibling and child pointers. We've replaced changed the code as so:
<code> class NewNode { /*various private fields with public setters and getters*/ private List<Node> children; private Node parent; } </code>
Now we have to go into the source code for JavaCC, and find every location where they generate code which directly accesses the field, and change it to instead uses the accessors. So we're looking for code like:
<code> System.out.println("myNode.nextNode = null;"); </code>
And want to change it to:
<code> System.out.println("myNode.setNextNode(null);"); </code>
The part where it really becomes a nightmare is conditional generation like changing
<code> System.out.println(varName + "."+ fieldName+" = "value";"); </code>
to
<code> System.out.println(varName + "."+ getMapFromFieldsTotheirAccessorStrings(fieldName, value)+";"); </code>
as a simple regular expression search won't yield a list of where the changes need to be made.
- Oliver
Dale King - 20 May 2006 05:22 GMT >>>> In Java it is less encapsulated. You are tying users of the class to >>>> the fact that the value is a field of the class. If that needs to [quoted text clipped - 20 lines] > output, it emits Java source code). Here's one of the classes that the > generated code manipulates: I didn't even think JavaCC was being actively developed anymore. A quick web search shows that it is. It's been kicked around a bit.
I switched to Antlr a long time ago. I find it superior to JavaCC and I have fond memories of JavaCC (I used JavaCC back in 1996 when it was still called Jack and that in fact was my first exposure to the Java language).
In Antlr the AST nodes are defined by an interface so there is no tight coupling and no use of exposed fields.
But I'm a little confused by your comments on JavaCC, because what I see in the documentation for JJTree (which I assume is the part of JavaCC you are talking about since you are ) they seem to use a simple Node interface that does not use fields. Or is this something else?
 Signature Dale King
Oliver Wong - 23 May 2006 15:24 GMT >> We're using JavaCC which is a parser generator (i.e. as part of its >> output, it emits Java source code). Here's one of the classes that the [quoted text clipped - 14 lines] > are talking about since you are ) they seem to use a simple Node interface > that does not use fields. Or is this something else? Sorry for calling it "Node". The example was from memory. The actual class I had to modify was Token (and even then, it's not the "standard" Token class that came with JavaCC, but one which had already been modified by a previous programmer). But we're not using JJTree; instead we're using JTB. We're also investigating ANTLR, but haven't made the switch yet.
- Oliver
Stefan Ram - 23 May 2006 22:30 GMT >But we're not using JJTree; instead we're using JTB. We're also >investigating ANTLR, but haven't made the switch yet. Just for curiosity: The Java SE still contains a »skeleton table driven LR parser«, viz., »com.sun.java_cup.internal.runtime.lr_parser«.
dimitar - 19 May 2006 17:04 GMT Dale, I had some assumptions (please read my first post in this thread.)
I don't advocate this style for public API classes, but I think it's ok for implementation classes. In my experience, almost always I've had to change the code when I'm opening up a class (even if it was only to add parameter checking and javadocs). As Thomas said, switching from direct field access to accessor methods is one click operation, so it's not really a problem.
Anything else?
Dale King - 19 May 2006 20:14 GMT > Dale, I had some assumptions (please read my first post in this thread.) > [quoted text clipped - 6 lines] > > Anything else? I didn't say that it is not OK to use it in certain situations. But it is wrong to say that it isn't less encapsulated or that it doesn't cause tighter coupling. It is less encapsulated and more tightly coupled. In some situations however that is not too much of a concern and may not be as important as competing factors.
 Signature Dale King
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|