views:

2824

answers:

19

What's the advantage of using getters and setters - that only get and set - instead of simply using public fields for those variables?

If getters and setters are ever doing more than just the simple get/set, I can figure this one out very quickly, but I'm not 100% clear on how:

public String foo;

is any worse than:

private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }

Whereas the former takes a lot less boilerplate code.


Compiling the list up here at the top of what seemed winners to me, from the viewpoint of a Java web dev:

  1. When you realize you need to do more than just set and get the value, you don't have to change every file in the codebase.
  2. You can perform validation here.
  3. You can change the value being set.
  4. You can hide the internal representation. getAddress() could actually be getting several fields for you.
  5. You've insulated your public interface from changes under the sheets.
  6. Some libraries expect this. Reflection, serialization, mock objects.
  7. Inheriting this class, you can override default functionality.
  8. You can have different access levels for getter and setter.
  9. Lazy loading.
  10. People can easily tell you didn't use Python.
+39  A: 

Because 2 weeks (months, years) from now when you realize that your setter needs to do more than just set the value, you'll also realize that the property has been used directly in 238 other classes :-)

ChssPly76
I'm sitting and starting at a 500k line app where it's never been needed. That said, if it's needed once, it'd start causing a maintenance nightmare. Good enough for a checkmark for me.
Dean J
I can only envy you and your app :-) That said, it really depends on your software stack as well. Delphi, for example (and C# - I think?) allows you to define properties as 1st class citizens where they can read / write a field directly initially but - should you need it - do so via getter / setter methods as well. Mucho convenient. Java, alas, does not - not to mention the javabeans standard which forces you to use getters / setters as well.
ChssPly76
Validation is a classic example of doing something special in the setter, especially if you don't fully trust the consumers of your code...
Rowland Shaw
While this is indeed a good reason for using accessors, many programming environments and editors now offer support for refactoring (either in the IDE or as free add-ins) which somewhat reduces the impact of the problem.
LBushkin
@LBushkin - assuming your code will not be consumed publicly.
UpTheCreek
A: 

As ChssPly76 said, you may want them to do more than just get and set.

But in your example, they aren't much worse. but you don't want to automatically write a getter and setter for every single variable. sometimes you may want to only do one or the other, or neither.

It's best to keep that layer of abstraction in objects, and to keep them as decoupled as possible.

GSto
+12  A: 

One advantage of accessors and mutators is that you can perform validation.

For example, if foo was public, I could easily set it to null and then someone else could try to call a method on the object. But it's not there anymore! With a setFoo method, I could ensure that foo was never set to null.

Accessors and mutators also allow for encapsulation - if you aren't supposed to see the value once its set (perhaps it's set in the constructor and then used by methods, but never supposed to be changed), it will never been seen by anyone. But if you can allow other classes to see or change it, you can provide the proper accessor and/or mutator.

Thomas Owens
+4  A: 

One of the basic principals of OO design: Encapsulation!

It gives you many benefits, one of which being that you can change the implementation of the getter/setter behind the scenes but any consumer of that value will continue to work as long as the data type remains the same.

Justin Niessner
+2  A: 

In languages which don't support "properties" (C++, Java) or require recompilation of clients when changing fields to properties (C#), using get/set methods is easier to modify. For example, adding validation logic to a setFoo method will not require changing the public interface of a class.

In languages which support "real" properties (Python, Ruby, maybe Smalltalk?) there is no point to get/set methods.

John Millikin
Re: C#. If you add functionality to a get/set wouldn't that require recompilation anyway?
steamer25
@steamer25: sorry, mis-typed. I meant that clients of the class will have to be recompiled.
John Millikin
+1  A: 

Additionally, this is to "future-proof" your class. In particular, changing from a field to a property is an ABI break, so if you do later decide that you need more logic than just "set/get the field", then you need to break ABI, which of course creates problems for anything else already compiled against your class.

Pete
+9  A: 

There are many reasons. My favorite one is when you need to change the behavior or regulate what you can set on a variable. For instance, lets say you had a setSpeed(int speed) method. But you want that you can only set a maximum speed of 100. You would do something like:

public void setSpeed(int speed) {
  if ( speed > 100 ) {
    this.speed = 100;
  } else {
    this.speed = speed;
  }
}

Now what if EVERYWHERE in your code you were using the public field and then you realized you need the above requirement? Have fun hunting down every usage of the public field instead of just modifying your setter.

My 2 cents :)

Peter D
Hunting down every usage of the public field shouldn't be that hard. Make it private and let the compiler find them.
Nathan Fellman
that's true of course, but why make it any harder than it was designed to be. The get/set approach is still the better answer.
Hardryv
Unless other projects also use that public field, ie if you share your library to external sources
PostMan
Tracking things down shouldn't be a problem in this day and age; I use an IDE. The type of projects I work on aren't ever shared to external sources.
Dean J
@Nathan: _Finding_ other usages isn't the problem. _Changing_ them all is.
Graeme Perrow
+3  A: 

One other use (in languages that support properties) is that setters and getters can imply that an operation is non-trivial. Typically, you want to avoid doing anything that's computationally expensive in a property.

Jason Baker
+5  A: 

Depends on your language. You've tagged this "object-oriented" rather than "Java", so I'd like to point out that ChssPly76's answer is language-dependent. In Python, for instance, there is no reason to use getters and setters. If you need to change the behavior, you can use a property, which wraps a getter and setter around basic attribute access. Something like this:

class Simple(object):
   def _get_value(self):
       return self._value -1

   def _set_value(self, new_value):
       self._value = new_value + 1

   def _del_value(self):
       self.old_values.append(self._value)
       del self._value

   value = property(_get_value, _set_value, _del_value)
jcdyer
Yes, I've said as much in a comment below my answer. Java is not the only language to use getters / setters as a crutch just like Python is not the only language able to define properties. The main point, however, still remains - "property" is not the same "public field".
ChssPly76
cool. Didn't know about properties
Nathan Fellman
@ChssPly76: but the main reason for using getters and setters is to prevent having to change the interface when you want to add more functionality, which means that it's perfectly acceptable--idiomatic even--to use public fields until such functionality is needed.
jcdyer
@jcd - not at all. You're defining your "interface" (public API would be a better term here) by exposing your public fields. Once that's done, there's no going back. Properties are NOT fields because they provide you with a mechanism to intercept attempts to access fields (by routing them to methods if those are defined); that is, however, nothing more than syntax sugar over getter / setter methods. It's extremely convenient but it doesn't alter the underlying paradigm - exposing fields with no control over access to them violates the principle of encapsulation.
ChssPly76
@ChssPly76—I disagree. I have just as much control as if they were properties, because I can make them properties whenever I need to. There is no difference between a property that uses boilerplate getters and setters, and a raw attribute, except that the raw attribute is faster, because it utilizes the underlying language, rather than calling methods. Functionally, they are identical. The only way encapsulation could be violated is if you think parentheses (`obj.set_attr('foo')`) are inherently superior to equals signs (`obj.attr = 'foo'`). Public access is public access.
jcdyer
+3  A: 

One aspect I missed in the answers so far, the access specification:

  • for members you have only one access specification for both setting and getting
  • for setters and getters you can fine tune it and define it separately
jdehaan
+30  A: 

There are actually many good reasons to consider using accessors rather than directly exposing fields of a class - beyond just the argument of encapsulation and making future changes easier.

Here are the some of the reasons I am aware of:

  • Encapsulation of behavior associated with getting or setting the property - this allows additional functionality (like validation) to be added more easily later.
  • Hiding the internal representation of the property while exposing a property using an alternative representation.
  • Insulating your public interface from change - allowing the public interface to remain constant while the implementation changes without effecting existing consumers.
  • Controlling the lifetime and memory management (disposal) semantics of the property - particularly important in non-managed memory environments (like C++ or Objective-C).
  • Providing a debugging interception point for when a property changes at runtime - debugging when and where a property changed to a particular value can be quite difficult without this in some languages.
  • Improved interoperability with libraries that are designed to operate against property getter/setters - Mocking, Serialization, and WPF come to mind.
  • Allowing inheritors to change the semantics of how the property behaves and is exposed by overriding the getter/setter methods.
  • Allowing the getter/setter to be passed around as lambda expressions rather than values.
  • Getters and setters can allow different access levels - for example the get may be public, but the set could be protected.
LBushkin
Tell, don't ask. http://www.pragprog.com/articles/tell-dont-ask
Dave Jarvis
+1. Just to add: Allowing lazy loading. Allowing copy on write.
Aurélien Vallée
+3  A: 

It can be useful for lazy-loading. Say the object in question is stored in a database, and you don't want to go get it unless you need it. If the object is retrieved by a getter, then the internal object can be null until somebody asks for it, then you can go get it on the first call to the getter.

I had a base page class in a project that was handed to me that was loading some data from a couple different web service calls, but the data in those web service calls wasn't always used in all child pages. Web services, for all of the benefits, pioneer new definitions of "slow", so you don't want to make a web service call if you don't have to.

I moved from public fields to getters, and now the getters check the cache, and if it's not there call the web service. So with a little wrapping, a lot of web service calls were prevented.

So the getter saves me from trying to figure out, on each child page, what I will need. If I need it, I call the getter, and it goes to find it for me if I don't already have it.

quillbreaker
A: 

In an object oriented language the methods, and their access modifiers, declare the interface for that object. Between the constructor and the accessor and mutator methods it is possible for the developer to control access to the internal state of an object. If the variables are simply declared public then there is no way to regulate that access.

Antz
+2  A: 

Lots of people talk about the advantages of getters and setters but I want to play devil's advocate. Right now I'm debugging a very large program where the programmers decided to make everything getters and setters. That might seem nice, but its a reverse-engineering nightmare.

Say you're looking through hundreds of lines of code and you come across this:

person.name = "Joe";

It's a beautifully simply piece of code until you realize its a setter. Now, you follow that setter and find that it also sets person.firstName, person.lastName, person.isHuman, person.hasReallyCommonFirstName, and calls person.update(), which sends a query out to the database, etc. Oh, that's where your memory leak was occurring.

Understanding a local piece of code at first glance is an important property of good readability that getters and setters tend to break. That is why I try to avoid them when I can, and minimize what they do when I use them.

Kai
+2  A: 

Well, It seems like the right place to quote an amusing post titled "Slutty Types" from Davy Brion's blog.

Slutty Types are types which:

  1. give you access to their privates without too many difficulties
  2. don’t really care about your intentions, or if they do, aren’t very clear on that
  3. occasionally seem like a good short-term fix
  4. can be used in a variety of ways, with different outcomes and none of them are guaranteed
  5. can not to be trusted
  6. really need to be tested
  7. will burn you sooner or later if you’re not careful
  8. become even more of a mess during the aging process

It's just another funny way to tell you why you should use encapsulation.

Moshe Levi
A: 

As other commenters have pointed out, other OO languages support creating getters and setters in a simpler way, such as Ruby which supports attr_reader, attr_writer, and attr_accessor, as described here

timmow
A: 

I would just like to throw the idea of annotation : @getter and @setter. With @getter, you should be able to obj = class.field but not class.field = obj. With @setter, vice versa. With @getter and @setter you should be able to do both. This would preserve encapsulation and reduce the time by not calling trivial methods at runtime.

fastcodejava
A: 

I spent quite a while thinking this over for the Java case, and I believe the real reasons are:

  1. Code to the interface, not the implementation
  2. Interfaces only specify methods, not fields

In other words, the only way you can specify a field in an interface is by providing a method for writing a new value and a method for reading the current value.

Those methods are the infamous getter and setter....

Thorbjørn Ravn Andersen
Okay, second question; in the case where it's a project where you're not exporting source to anyone, and you have full control of the source... are you gaining anything with getters and setters?
Dean J
In any non-trivial Java project you need to code to interfaces in order to make things manageable and testable (think mockups and proxy objects). If you use interfaces you need getters and setters.
Thorbjørn Ravn Andersen
A: 

I wanted to post a real world example I just finished up:

background - I hibernate tools to generate the mappings for my database, a database I am changing as I develop. I change the database schema, push the changes and then run hibernate tools to generate the java code. All is well and good until I want to add methods to those mapped entities. If I modify the generated files, they will be overwritten every time I make a change to the database. So I extend the generated classes like this:

package com.foo.entities.custom
class User extends com.foo.entities.User{
     public Integer getSomething(){
         return super.getSomething();             
     }
     public void setSomething(Integer something){
         something+=1;
         super.setSomething(something); 
     }
}

What I did above is override the existing methods on the super class with my new functionality (something+1) without ever touching the base class. Same scenario if you wrote a class a year ago and want to go to version 2 without changing your base classes (testing nightmare). hope that helps.

ebt