April 15, 2005
On Uniform Access
If you remember your Programming 101 class, you probably also remember an instructor threatening blood and thunder should he ever catch you directly exposing instance variables to the public. The insistence on using getter and setter methods in Java et al. stems from something called Uniform Access Principle:
All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation.
While I'm convinced that the Uniform Access Principle is a dogma worth subscribing to, its implementations often lack the love it deserves. For instance, when the designers of Java decided to go Uniform Access, their solution was not to make methods and instance variables look alike. Instead they agreed to make everything look like a method. That is why Java forces you to write foo.setBaz(bar.getBaz()) when the poet in you really thinks foo.baz = bar.baz.
Things look much brighter in the world of Ruby. Ruby lets you "assign" values to methods, so you can skip the whole accessor mess with getBaz() and setBaz(..). If baz is an instance variable, just expose it as such:
attr_accessor :baz
Should you ever change your mind about the nature of baz you can overwrite its accessors like this:
def baz # funky code for getting baz end def baz=(value) # funky code for setting baz end
Something similiar is possible in vanilla Perl, but it's a pain in the ass. See perltie for the ugly details and my Reformed Perl hack for an example for how to hide the mess.
While C# promises Uniform Access Nirvana in the spirit of Eiffel and Ruby, its implementation falls short in some important points. In C# you may define properties which look like this:
public Klass Baz {
get {
// funky code for getting Baz
}
set {
// funky code for setting Baz
}
}
The issues:
- The property above will mutate into
get_Bazandset_Bazduring compilation. That means while most of your C# source is ignorant of how access toBazis implemented, compiled code is not; so better pay attention when accessing a class using reflection. - It is impossible to overload property setters.
set_Baztakes anotherKlassas its value and that's all you get. - An interface which includes a get/set property cannot be implemented with a public instance variable of the same name. You need to type out the whole property construct instead, even though all it does is reading and writing to a variable.
I hope to have shed some light on the state of Uniform Access. For further discussion of the topic, check out the always excellent Portland Pattern Repository Wiki.
Comments
Of course, Perl6 will do that as part of boiling the ocean. And it's already lowered the landing gear.
Posted by Aristotle Pagaltzis (#)
I think "Perl6 will do that" can be considered a true statement regardless of the current context :)
Pugs sounds like I should have taken Haskell more serious when I had the chance.
Posted by
Henning
(#)
Post a comment
Thanks for signing in, . Now you can comment. (sign out)
(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)