Is it okay to expose the state of an Immutable object?
Having come across the concept of immutable objects recently, I would like to know the best practices for controlling access to the state. Even though the object oriented part of my brain makes me want to cower in fear at the sight of public members, I see no technical issues with something like this:
public class Foo {
public final int x;
public final int y;
public Foo( int x, int y) {
this.x = x;
this.y = y;
}
}
I would feel more comfortable declaring the fields as private
and providing getter methods for each but this seems overly complex when the state is explicitly read only.
What is the best practice for providing access to the state of an immutable object?
It depends entirely on how you're going to use the object. Public fields aren't inherently evil, it's just bad to default everything to being public. For example the java.awt.Point class makes its x and y fields public, and they aren't even final. Your example seems like a fine use of public fields, but then again you might not want to expose all of the internal fields of another immutable object. There is no catch-all rule.
I have thought the same in the past but usually end up making variables private and using getters and setters so that later on I'll still have the option of making changes to the implementation while keeping the same interface.
This did remind me of something I read recently in "Clean Code" by Robert C. Martin. In chapter 6 he gives a slightly different perspective. For example, on page 95 he states
"Objects hide their data behind abstractions and expose functions that operate on that data. Data structure expose their data and have no meaningful functions."
And on page 100:
The quasi-encapsulation of beans seems to make some OO purists feel better but usually provides no other benefit.
Based on the code sample, the Foo class would seem to be a data structure. So based on what I understood from the discussion in Clean Code (which is more than just the two quotes I gave), the purpose of the class is to expose data, not functionality, and having getters and setters probably does not do much good.
Again, in my experience, I have usually gone ahead and used the "bean" approach of private data with getters and setters. But then again, no one ever asked me to write a book about how to write better code so maybe Martin has something to say.