Why to use Getters/Setters instead of public fields

November 10, 2006


Rene Magritte
1898-1967
La Perspective Amoureuse
3,000,000-4,000,000 USD

This past weekend, Eileen and I were in New York City and one of the things we did was visit the auction preview at Sotheby's. A few days before Sotheby's has an auction, they put all of the works on display for the general public to see before they are auctions off. My favorite was the one shown to the right, Magritte's La Perspective Amoureuse, which went for $3,376,000.

The labels for the paintings were similar to what I have shown here. They have the artist, the years the artist lived, the title of the work, and the amount of money that they expect the work to sell for in the auction. The price is listed as a range.

I was recently working with a data structure similar to this and I came across a good example of why you use getters and setters instead of public fields.

A common idiom in Java, and in almost all objected-oriented programming languages is the concept of getters and setters. People call them different things, I've gotten used to calling them getters and setters, most likely because I do most of my programming in Java, and in Java getter and setters look like this:

private String range;

public String getRange() {
    return range;
}

public void setRange(String range) {
    this.range = range;
}

The syntax is a little verbose, but luckily all Java IDEs allow you to auto-generate them based on the private fields. This is one of the many reasons why programming in Java is nearly impossible without a good IDE, but I digress.

When you use this object in another object, you can't access the private field range directly, so you call work.getRange(). The JSTL EL language simplifies this even more, so that when you use work.range, it calls work.getRange() for you. This alone has made this pattern almost unavoidable, but every once in a while I'll see someone suggesting that the getters and setters are unnecessary, they lead to more lines of code and make the code harder to maintain. They'll say, why can't I just do this:

public String range;

And be done with, it? Object-Oriented purists will say that it provides encapsulation, and they are right, but here's a real world example that shows how it helps.

Let's say you are using the getter in your code everywhere. So you have lots of JSP pages that have ${work.range} to display the range of the work . But then you decide you need create a search page to search for your works. That means you need to store the min and max values as a numeric type such as Double. So you can refactor your code to look like this:

private Double minPrice;
private Double maxPrice;

public String getRange() {
    return "$"+getMinPrice()+" - $"+getMaxPrice();
}

and you won't have to make any changes to your code elsewhere. There are a couple of more odds and ends to take care of, creating the minPrice and maxPrice getters and setters, checking for null in the getRange method, dealing with removing the setRange method, but you get the picture.

Ruby makes this even easy. Even though I'm still not sold on Rails, I gotta say I do think Ruby is cool. Here's how this works in Ruby. First you create your class:

class Work
    def initialize(range)
        @range = range
    end
end

initialize the constructor, and @range is an instance variable, the equivalent of private String range in Java, except you don't explicitly define it. In ruby, all instance variables are private. If you fire up irb, you can see this in action:

irb(main):001:0> require 'Work.rb'
=> true
irb(main):002:0> work = Work.new "$3,000,000 - $4,000,000"
=> #<Work:0x2c9a994 @range="$3,000,000 - $4,000,000">
irb(main):003:0> work.range
NoMethodError: undefined method `range' 
for #<Work:0x2c9a994 @range="$3,000,000 - $4,000,000">
        from (irb):3

As you can see, Ruby is looking for a method called "range". In Ruby, the getter is the same name as the field. The setter is the name of the field with an "=" appended to it.

irb(main):004:0> work.range = ""
NoMethodError: undefined method `range=' 
for #<Work:0x2c9a994 @range="$3,000,000 - $4,000,000">

But as you can see, you end up using it just like a normal variable assignment. So let's create the getters and setters:

class Work
    attr_accessor :range, :title
end

attr_accessor is how you create getters and setters. And you can see that you do more than one in one like Here it is in action:

irb(main):001:0> require 'Work.rb'
=> true
irb(main):002:0> work = Work.new
=> #<Work:0x2c9bbdc>
irb(main):003:0> work.range = "$3,000,000 - $4,000,000"
=> "$3,000,000 - $4,000,000"
irb(main):004:0> work.range
=> "$3,000,000 - $4,000,000"
irb(main):005:0> work.title = "La Perspective Amoureuse"
=> "La Perspective Amoureuse"
irb(main):006:0> work.title
=> "La Perspective Amoureuse"
irb(main):007:0>

So here it is with our new minPrice and maxPrice fields:

class Work
    attr_accessor :min_price, :max_price, :title
    def range
        "$#{min_price} - #{max_price}"
    end
end

And in action:

irb(main):001:0> require 'Work.rb'
=> true
irb(main):002:0> work = Work.new
=> #<Work:0x2c995f8>
irb(main):003:0> work.min_price = 3000000
=> 3000000
irb(main):004:0> work.max_price = 4000000
=> 4000000
irb(main):005:0> work.range
=> "$3000000 - 4000000"

Posted in Technology | Tags Ruby, Java

Comments Comments Feed

1. I still don't see the use for always using getters/setters.

In this instance you could have still had a public string range originally. And only when you needed to change it's storage methodology would you need to remove the public var and implement getters/setters for the range parameter. Would look identical to client code

# Posted By DJ on Monday, May 4 2009 at 9:19 AM

2. @DJ,

The client code in Java would not be the same, you would have to change work.range to work.getRange()

# Posted By Paul Barry on Monday, May 4 2009 at 1:22 PM

3. Find ugg and Australian sheepskin boots, learn the history behind the Ugg boot, and when and what to wear with Cheap ugg boots, as well as cleaning and caring forAuthentic Ugg boots,Cheap ugg cardy boots,20%-40% high discount

# Posted By p on Wednesday, September 1 2010 at 2:19 PM

4.
Cheap nfl jerseys are your best choice, and retail nfl apparell and drop shipping are accepted as well. Grade cheap nfl sports jerseys,Competitive price and Best service, We do hope nfl jerseys usa to do long-term business with every clients and help you improvefootball jerseys more benefit from your market.

# Posted By fewrewree on Wednesday, September 1 2010 at 7:32 PM

Add a Comment

(If you leave this blank, your IP address will be displayed instead)

(Optional, will not be displayed on the site)