Java 为什么要使用 getter 和 setter/accessors?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1568091/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why use getters and setters/accessors?
提问by Dean J
What's the advantage of using getters and setters - that only get and set - instead of simply using public fields for those variables?
使用 getter 和 setter(仅获取和设置)而不是简单地对这些变量使用公共字段有什么好处?
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:
如果 getter 和 setter 所做的不仅仅是简单的 get/set,我可以很快弄清楚这一点,但我不是 100% 清楚如何:
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.
而前者需要更少的样板代码。
采纳答案by LBushkin
There are actually many good reasonsto consider using accessorsrather 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 affecting 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.
- 封装与获取或设置属性相关的行为 - 这允许以后更容易地添加附加功能(如验证)。
- 隐藏属性的内部表示,同时使用替代表示公开属性。
- 使您的公共接口免受更改 - 允许公共接口在实现更改时保持不变,而不会影响现有使用者。
- 控制属性的生命周期和内存管理(处置)语义——在非托管内存环境(如 C++ 或 Objective-C)中尤其重要。
- 在运行时属性更改时提供调试拦截点 - 在某些语言中,如果没有此功能,则在何时何地调试属性更改为特定值可能会非常困难。
- 改进了与旨在针对属性 getter/setter 操作的库的互操作性 - 想到了模拟、序列化和 WPF。
- 允许继承者通过覆盖 getter/setter 方法来更改属性行为和公开方式的语义。
- 允许 getter/setter 作为 lambda 表达式而不是值传递。
- getter 和 setter 可以允许不同的访问级别 - 例如 get 可能是公开的,但 set 可以受到保护。
回答by ChssPly76
Because 2 weeks (months, years) from now when you realize that your setter needs to do morethan just set the value, you'll also realize that the property has been used directly in 238 other classes :-)
因为从2现在周(月,年),当你意识到你的二传手需要做更多的比刚才设置的值,你也会意识到,财产已经在其他238类直接使用:-)
回答by Thomas Owens
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
.
例如,如果foo
是公共的,我可以轻松地将其设置为null
,然后其他人可以尝试调用该对象的方法。但它已经不在了!使用一种setFoo
方法,我可以确保它foo
从未设置为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.
访问器和修改器也允许封装——如果你不应该在设置后看到值(也许它在构造函数中设置然后被方法使用,但永远不应该被改变),它永远不会被任何人看到。但是,如果您可以允许其他类查看或更改它,则可以提供适当的访问器和/或修改器。
回答by Justin Niessner
One of the basic principals of OO design: Encapsulation!
OO 设计的基本原则之一:封装!
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.
它为您提供了许多好处,其中之一是您可以在幕后更改 getter/setter 的实现,但只要数据类型保持不变,该值的任何使用者都将继续工作。
回答by John Millikin
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.
在不支持“属性”(C++、Java)或在将字段更改为属性(C#)时需要重新编译客户端的语言中,使用 get/set 方法更容易修改。例如,向 setFoo 方法添加验证逻辑不需要更改类的公共接口。
In languages which support "real" properties (Python, Ruby, maybe Smalltalk?) there is no point to get/set methods.
在支持“真实”属性的语言(Python、Ruby,也许是 Smalltalk?)中,获取/设置方法没有意义。
回答by Pete
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.
此外,这是为了“面向未来”您的课程。特别是,从字段更改为属性是 ABI 中断,因此如果您稍后决定需要更多逻辑而不仅仅是“设置/获取字段”,那么您需要中断 ABI,这当然会给任何事情带来问题else 已经针对您的课程进行了编译。
回答by Peter D
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:
有很多原因。我最喜欢的是当您需要更改行为或调节可以在变量上设置的内容时。例如,假设您有一个 setSpeed(int speed) 方法。但是您希望您只能将最大速度设置为 100。您可以执行以下操作:
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.
现在,如果您在代码中的每个地方都使用公共字段,然后您意识到需要上述要求怎么办?寻找公共领域的每一次使用,而不是仅仅修改你的 setter,玩得开心。
My 2 cents :)
我的 2 美分 :)
回答by Jason Baker
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.
另一种用途(在支持属性的语言中)是 setter 和 getter 可以暗示操作是非平凡的。通常,您希望避免在属性中执行任何计算成本高的操作。
回答by jcdyer
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:
取决于你的语言。你已经标记了这个“面向对象”而不是“Java”,所以我想指出 ChssPly76 的答案是依赖于语言的。例如,在 Python 中,没有理由使用 getter 和 setter。如果您需要更改行为,您可以使用一个属性,它围绕基本属性访问包装了一个 getter 和 setter。像这样的东西:
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)
回答by jdehaan
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
- 对于成员,您只有一个访问规范来设置和获取
- 对于 setter 和 getter,您可以对其进行微调并分别定义