I am completing Sun/Oracle's Trail (http://docs.oracle.com/javase/tutorial/java/TOC.html) and it keeps reiterating the importance of encapsulation.
How important, really, is encapsulation? I mean, if I may need to access the value of a given class field, why would I do so through a method when I could just access the field directly? Since the field would be accessed through its corresponding object anyway, where could this really go wrong?
Is it just for code extensibility purposes? In other words, because that way in the future if I decide I want to somehow alter or sanitize the field before returning it I can?
I'm more looking for an example or two than anything.
Encapsulation is not only a matter of making getter and setter for a field.
It's about:
Even if you as you said "need to access the value of a given class field" you can't be sure that this requirement won't change (cause it will most time).
Encapsulation allows your object to make guarantees (part of an object's contract), by giving the object control over its own data, which happens to make debugging considerably easier. Consider this class:
Any other code is free to set
travelSpeed
to zero, which will cause all future calls to the calculateTravelTime method to fail. Worse, you will have no way to know who set it to zero, so debugging the problem is going to take a long time.However, with encapsulation, the class has total control over the value, and can guarantee that it is always valid:
Now it is absolutely impossible for any outside code to place the object in an invalid state. If anyone tries to do so, the resulting IllegalArgumentException will provide you with an informative stack trace that will immediately expose the culprit.
As a bonus, all other code which uses this class no longer needs to do any checks for its validity, because the object itself can already guarantee that validity. This makes overall development much faster for everyone.
Validation.
If you don't use a method, you can't add any validation on the field unless you validate it at every place you want to access the field: unsustainable.
It also separates the data from your class from the outside world. By hiding the actual implementation of data behind methods, you can manipulate your data the way you want (now and in the future) and no other pieces of code will get broken. This allows you to change the way something is represented without a problem, as long as you make sure it can still be returned trough the existing method.
Actually, I think you're thinking about this the wrong way. The issue isn't encapsulation per se, it's decoupling the behavior of your objects from their data.
Fields are data -- they are part of the internal state of the object. Methods are part of the object's API. Objects shouldn't just be clusters of fields -- if your objects are just dumb collections of data, then that's not object-oriented programming, that's just structured programming.
Objects should be designed to represent real-world entities, and have methods that represent operations you could take on those real-world entities. To put it another way, you don't ask an object for its fields (e.g.
getFoo()
,getBar()
) to pass those to other functions -- instead you should put the relevant operations (e.g.purchase()
,validate()
, etc.) as methods directly on the object.That said, there's nothing wrong with having accessor methods -- sometimes you do need to actually retrieve the value. But by making those accessors methods instead of just exposing fields directly, you are implementing information hiding: users of your class don't need to know what the internal state looks like to be able to use it or get data from it.
Basically, in Java (or in any object-oriented language) classes are nouns, and methods are verbs. If you write classes that don't have any verbs, then you're programming in the kingdom of nouns.