One of my classes has a field which contains a Set. This field is only ever filled in the constructor, and then read by other classes. Originally I had something like this:
public class Foo {
public final Set<String> myItems;
public Foo(Collection<String> theirItems) {
this.myItems = new LinkedHashSet<String>(theirItems);
}
}
But this goes against OO best practices, by which myItems should be private, and only accessed via setters and getters. So then I changed it to:
public class Foo {
private final Set<String> myItems;
public Foo(Collection<String> theirItems) {
this.myItems = new LinkedHashSet<String>(theirItems);
}
public Set<String> getItems() {
return myItems;
}
}
Now myItems is private, but whoever calls getItems() can still add/remove items at will, which is essentially the same situation I had before. (I'm not actually concerned about somebody changing the item contents, this is more a theoretical question)
So then I changed getItems() to return an array:
public String[] getItems() {
return myItems.toArray(new String[myItems.size()]);
}
Now my items are really private. Unfortunately, I know that the object which will read the items will actually want to work with a Set, so it would have to convert the array right back. I could also return a copy of myItems:
public Set<String> getItems() {
return new LinkedHashSet<String>(myItems);
}
This gives the caller what they want, but creates a new Set on each access.
What do you do in a situation like this - preserve privacy at all costs, and accept the conversion/copying of the original structure, or sacrifice the control over the contents of the collection and rely on responsible callers?