将光标移到/点击文章中的句子上,可以查看译文。      显示繁体中文内容    显示简体中文内容

Why use getters and setters?
为什么使用getters 和setters?

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.
时间:

A public field is not worse than a getter/setter pair that does nothing except returning the field and assigning to it.First, it's clear that (in most languages) there is no functional difference.any difference must be in other factors, like maintainability or readability.

An oft-mentioned advantage of getter/setter pairs, isn't.there's this claim that you can change the implementation and your clients don't have to be recompiled.Supposedly, setters let you add functionality like validation later on and your clients don't even need to know about it.However, adding validation to a setter is a change to its preconditions, a violation of the previous contract, which was, quite simply,"you can put anything in here, and you can get that same thing later from the getter".

So, now that you broke the contract, changing every file in the codebase is something you should want to do, not avoid.if you avoid it you're making the assumption that all the code assumed the contract for those methods was different.

If that should not have been the contract, then the interface was allowing clients to put the object in invalid states.that's the exact opposite of encapsulation if that field could not really be set to anything from the start, why wasn't the validation there from the start?

This same argument applies to other supposed advantages of these pass-through getter/setter pairs :if you later decide to change the value being set, you're breaking the contract.if you override the default functionality in a derived class, in a way beyond a few harmless modifications (like logging or other non-observable behaviour), you're breaking the contract of the base class.that is a violation of the Liskov Substitutability Principle, which is seen as one of the tenets of OO.

If a class has these dumb getters and setters for every field, then it is a class that has no invariants whatsoever, no contract.is that really object-oriented design?if all the class has is those getters and setters, it's just a dumb data holder, and dumb data holders should look like dumb data holders :


class Foo {
public:
 int DaysLeft;
 int ContestantNumber;
};

Adding pass-through getter/setter pairs to such a class adds no value.other classes should provide meaningful operations, not just operations that fields already provide.that's how you can define and maintain useful invariants.

Client :"What can i do with an object of this class?"
Designer :"You can read and write several variables."
Client :"Oh... cool, i guess?"

There are reasons to use getters and setters, but if those reasons don't exist, making getter/setter pairs in the name of false encapsulation gods is not a good thing.Valid reasons to make getters or setters include the things often mentioned as the potential changes you can make later, like validation or different internal representations.or maybe the value should be readable by clients but not writable (for example, reading the size of a dictionary), so a simple getter is a nice choice.but those reasons should be there when you make the choice, and not just as a potential thing you may want later.this is an instance of YAGNI ( you ain't Gonna need it ).

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.

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 : )

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.

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)

...