Java 接口使用指南——接口中的 getter 和 setter 是坏的吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1130294/
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
Java Interface Usage Guidelines -- Are getters and setters in an interface bad?
提问by His
What do people think of the best guidelines to use in an interface? What should and shouldn't go into an interface?
人们如何看待在界面中使用的最佳指南?什么应该和不应该进入界面?
I've heard people say that, as a general rule, an interface must only define behavior and not state. Does this mean that an interface shouldn't contain getters and setters?
我听说有人说,作为一般规则,接口必须只定义行为而不是状态。这是否意味着接口不应该包含 getter 和 setter?
My opinion: Maybe not so for setters, but sometimes I think that getters are valid to be placed in an interface. This is merely to enforce the implementation classes to implement those getters and so to indicate that the clients are able to call those getters to check on something, for example.
我的意见:对于 setter 来说可能不是这样,但有时我认为 getter 放在接口中是有效的。例如,这只是为了强制实现类来实现这些 getter,从而表明客户端能够调用这些 getter 来检查某些东西。
采纳答案by oxbow_lakes
I think that there are two types of interfaces declared in general:
我认为一般有两种类型的接口声明:
- a service description. This might be something like
CalculationService
. I don't think that methodsgetX
should be in this sort of interface, and certainlynotsetX
. They quite clearly imply implementation detail, which is not the job of this type of interface. - a data model- exists solely to abstract out the implementation of data objects in the system. These might be used to aid in testing or just because some people as old as me remember the days when (for example) using a persistence framework tied you down to having a particular superclasss (i.e. you would choose to implement an interface in case you switched your persistence layer). I think that having JavaBean methods in this type of interface is entirely reasonable.
- 一个服务描述。这可能类似于
CalculationService
. 我不认为方法getX
应该在这种接口中,当然也不应该setX
。它们很清楚地暗示了实现细节,这不是此类接口的工作。 - 一个数据模型-出的数据执行系统中的对象只存在于抽象。这些可能用于帮助测试,或者只是因为一些像我一样大的人记得(例如)使用持久性框架将您绑定到具有特定超类的日子(即,您会选择实现一个接口,以防万一您切换你的持久层)。我认为在这种类型的接口中使用 JavaBean 方法是完全合理的。
Note: the collections classes probably fit in to type #2
注意:集合类可能适合类型 #2
回答by Jon Skeet
I don't see why an interface can't define getters and setters. For instance, List.size()
is effectively a getter. The interface must define the behaviour rather than the implementationthough - it can't say how you'll handlethe state, but it can insist that you can get it and set it.
我不明白为什么接口不能定义 getter 和 setter。例如,List.size()
实际上是一个吸气剂。接口必须定义行为而不是实现- 它不能说明您将如何处理状态,但它可以坚持您可以获取并设置它。
Collection interfaces are all about state, for example - but different collections can store that state in radically different ways.
例如,集合接口都是关于状态的——但是不同的集合可以以完全不同的方式存储该状态。
EDIT: The comments suggest that getters and setters imply a simple field is used for backing storage. I vehemently disagree with this implication. To my mind there's an implication that it's "reasonably cheap" to get/set the value, but not that it's stored as a field with a trivial implementation.
编辑:评论表明 getter 和 setter 意味着一个简单的字段用于支持存储。我强烈不同意这种暗示。在我看来,这意味着获取/设置值“相当便宜”,但并不是说它存储为具有简单实现的字段。
EDIT: As noted in the comments, this is made explicit in the JavaBeans specificationsection 7.1:
编辑:如评论中所述,这在JavaBeans 规范第 7.1 节中进行了明确:
Thus even when a script writer types in something such as
b.Label = foo
there is still a method call into the target object to set the property, and the target object has full programmatic control.So properties need not just be simple data fields, they can actually be computed values. Updates may have various programmatic side effects. For example, changing a bean's background color property might also cause the bean to be repainted with the new color."
因此,即使脚本编写者输入某些内容,例如
b.Label = foo
仍然有一个方法调用到目标对象来设置属性,并且目标对象具有完全的编程控制。因此,属性不仅是简单的数据字段,它们实际上还可以是计算值。更新可能会产生各种程序性副作用。例如,更改 bean 的背景颜色属性也可能导致 bean 被重新绘制为新颜色。”
If the supposed implication weretrue, we might just as well expose properties as fields directly. Fortunately that implication doesn'thold: getters and setters are perfectly within their rights to compute things.
如果假设的含义是真的,我们不妨直接公开属性作为字段。幸运的是,这种暗示并不成立:getter 和 setter 完全在他们计算事物的权利范围内。
For example, consider a component with
例如,考虑一个组件
getWidth()
getHeight()
getSize()
Do you believe there's an implication that there are three variables there? Would it not be reasonable to either have:
您是否认为存在三个变量的含义?是否有以下两种情况是不合理的:
private int width;
private int height;
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Size getSize() {
return new Size(width, height); // Assuming an immutable Size type
}
Or (preferrably IMO):
或者(最好是 IMO):
private Size size;
public int getWidth() {
return size.getWidth();
}
public int getHeight() {
return size.getHeight();
}
public Size getSize() {
return size;
}
Here either the size property or the height/width properties are for convenience only - but I don't see that that makes them invalid in any way.
这里的 size 属性或 height/width 属性只是为了方便 - 但我不认为这会使它们以任何方式无效。
回答by Kevin Peterson
I don't think a bean should have an interface on top of it, in general. A javabean is an interface in the more general meaning. An Interface specifies the external contract of something more complex. A javabean's external contract and its internal representation are identical.
一般来说,我认为 bean 上不应该有一个接口。javabean 是更一般意义上的接口。接口指定了更复杂的东西的外部契约。javabean 的外部契约及其内部表示是相同的。
I wouldn't say that you shouldn't have getters in an interface, though. It makes perfect sense to have a ReadableDataThingie interface that is implemented by DataThingieBean.
不过,我不会说你不应该在接口中使用 getter。拥有一个由 DataThingieBean 实现的 ReadableDataThingie 接口是非常有意义的。
回答by akarnokd
For further reading: Practical API Design Confessions of a Java Framework Architect (Jaroslav Tulach, 2008, Apress).
进一步阅读:Java 框架架构师的实用 API 设计自白(Jaroslav Tulach,2008 年,Apress)。
回答by Paul McKenzie
This touches upon the whole Getter/Setters are evil topic which is addressed multiple times on this site and elsewhere.
这涉及整个 Getter/Setter 是邪恶的话题,该话题在本网站和其他地方多次提及。
I tend to favour not having accessors in the interface, but to add collaborators using constructor arguments to the implementation.
我倾向于在接口中不使用访问器,而是使用构造函数参数向实现添加协作者。
回答by soru
The fact that the straightforward implementation of something is as a getter shouldn't stop it being in an interface if it needs to be.
如果需要的话,某些东西的直接实现是作为 getter 的事实不应该阻止它出现在接口中。
回答by Brian Agnew
There's nothing inherently evil about getters/setters. However:
getter/setter 没有本质上的邪恶。然而:
- I tend to make my objects immutable (in the first instance) with respect to the fields they contain. Why ? I instantiate most things during the construction phase. If I want to change something later then I relax those restrictions. So my interfaces will tend to contain getters, but not setters (there are other benefits - particularly threading).
- I want my objects to do things for me, not the other way around. So when one of my objects acquires a number of getters, I start to ask whether that object should have more functionality in it, rather than exposing all its data for something else to work with. See this answerfor more detail.
- 我倾向于使我的对象在它们包含的字段方面不可变(首先)。为什么 ?我在构建阶段实例化了大多数东西。如果我以后想更改某些内容,那么我会放宽这些限制。所以我的接口将倾向于包含 getter,但不包含 setter(还有其他好处 - 特别是线程)。
- 我希望我的对象为我做事,而不是相反。因此,当我的一个对象获得多个 getter 时,我开始询问该对象是否应该具有更多功能,而不是将其所有数据暴露给其他对象使用。有关更多详细信息,请参阅此答案。
These are all guidelines, note.
请注意,这些都是指导方针。
回答by IAdapter
I used those kind of interfaces, for example we had classes with fields beginDate, endDate. Those fields were in many classes and I had one use case I need to get those dates for different objects, so I extracted interface and was very happy :)
我使用了那种接口,例如我们有包含字段 beginDate、endDate 的类。这些字段在许多类中,我有一个用例我需要获取不同对象的日期,所以我提取了接口并且非常高兴:)
回答by Newtopian
Basically if the answer to "Do I need to know the value of [state, property, whateverThignAMaGit] in order to work with an instance of it ?" then yes... the accessors belong in the interface.
基本上,如果回答“我是否需要知道 [state, property,whateverThignAMaGit] 的值才能使用它的实例?” 那么是的......访问器属于接口。
List.size() from John above is a perfect example of a getter that needs to be defined in an interface
上面 John 的 List.size() 是需要在接口中定义的 getter 的完美示例
回答by Newtopian
Getters are used to query the state of an object - which you can really avoid when designing your interface. Read http://www.pragprog.com/articles/tell-dont-ask
Getter 用于查询对象的状态 - 在设计界面时您可以真正避免这种情况。阅读http://www.pragprog.com/articles/tell-dont-ask