42

人们认为在界面中使用的最佳指南是什么?什么应该和不应该进入界面?

我听人说过,作为一般规则,接口只能定义行为而不是状态。这是否意味着接口不应该包含 getter 和 setter?

我的观点:对于 setter 来说可能不是这样,但有时我认为 getter 可以有效地放置在接口中。这仅仅是为了强制实现类来实现这些 getter,从而表明客户端能够调用这些 getter 来检查某些东西。

4

11 回答 11

28

我不明白为什么接口不能定义 getter 和 setter。例如,List.size()实际上是一个吸气剂。接口必须定义行为而不是实现——它不能说你将如何处理状态,但它可以坚持你可以获取并设置它。

例如,集合接口都是关于状态的——但不同的集合可以以完全不同的方式存储该状态。

编辑:评论表明 getter 和 setter 暗示一个简单的字段用于支持存储。我强烈不同意这种暗示。在我看来,这意味着获取/设置该值“相当便宜”,但并不是说它被存储为具有简单实现的字段。


编辑:如评论中所述,这在JavaBeans 规范第 7.1 节中明确表示:

因此,即使脚本编写者输入了一些东西,例如b.Label = foo 仍然有一个方法调用目标对象来设置属性,并且目标对象具有完全的编程控制。

所以属性不必只是简单的数据字段,它们实际上可以是计算值。更新可能有各种程序性副作用。例如,更改 bean 的背景颜色属性也可能导致 bean 用新颜色重新绘制。”


如果假设的含义真的,我们也可以直接将属性公开为字段。幸运的是,这种暗示并不成立:getter 和 setter 完全在他们计算事物的权利范围内。

例如,考虑一个组件

getWidth()
getHeight()
getSize()

你认为这意味着存在三个变量吗?两者都不是合理的:

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
}

或者(最好是国际海事组织):

private Size size;

public int getWidth() {
    return size.getWidth();
}

public int getHeight() {
    return size.getHeight();
}

public Size getSize() {
    return size;
}

这里的 size 属性或 height/width 属性只是为了方便起见——但我不认为这会使它们以任何方式无效。

于 2009-07-15T09:19:11.220 回答
14

我认为一般声明了两种类型的接口:

  1. 服务描述。这可能类似于CalculationService. 我认为方法getX不应该在这种接口中,当然也不应该setX。它们非常清楚地暗示了实现细节,这不是这种接口的工作。
  2. 数据模型- 仅用于抽象出系统中数据对象的实现。这些可能用于帮助测试,或者只是因为像我这样年长的人还记得(例如)使用持久性框架将您束缚于拥有特定超类的日子(即,您会选择实现接口以防切换你的持久层)。我认为在这种类型的接口中使用 JavaBean 方法是完全合理的。

注意:集合类可能适合类型 #2

于 2009-07-15T09:58:43.073 回答
12

getter/setter 本身并没有什么坏处。然而:

  1. 我倾向于使我的对象(首先)相对于它们包含的字段是不可变的。为什么 ?我在构建阶段实例化了大多数东西。如果我以后想更改某些内容,那么我会放宽这些限制。所以我的接口倾向于包含getter,而不是setter(还有其他好处——尤其是线程)。
  2. 我希望我的对象为我做事,而不是相反。因此,当我的一个对象获得许多 getter 时,我开始询问该对象是否应该具有更多功能,而不是公开其所有数据以供其他对象使用。有关更多详细信息,请参阅此答案

这些都是指导方针,请注意。

于 2009-07-15T10:08:13.260 回答
6

一般来说,我认为 bean 上不应该有一个接口。javabean 是更一般意义上的接口。接口指定更复杂事物的外部契约。javabean 的外部契约和它的内部表示是相同的。

不过,我不会说你不应该在接口中使用 getter。拥有一个由 DataThingieBean 实现的 ReadableDataThingie 接口非常有意义。

于 2009-07-15T09:19:40.207 回答
2

我听人说过,作为一般规则,接口只能定义行为而不是状态。这是否意味着接口不应该包含 getter 和 setter?

对于初学者,至少使用 Java 并排除 Exception 声明,您无法在没有状态的情况下定义完整的行为。在 Java 中,接口不定义行为。他们不能。他们定义的是类型;承诺实现一组特征签名,可能带有一些后置条件 wrt 例外。但就是这样。行为和状态由实现这些接口的类定义。

其次,如果在接口中定义了 getter 和 setter,它们并没有真正定义完整的行为(另一个是用于读取,一个用于写入属性。)您可以在 setter 和 getter 后面有复杂的行为,但它们可以只能在实际的类中实现。Java 语言中没有任何东西可以让我们在接口中自由定义行为,除非是最严格的情况。

考虑到这一点,在接口中使用 setter 和 getter 并没有错——在语法和语义上。

如果您的应用程序建模良好并且问题需要您有一个定义 setter 和 getter 的接口,为什么不呢。例如,看一下 ServletResponse 接口。

现在,如果我们从实现符合 JavaBeans 规范的类的角度来看 getter 和 setter,那么您不需要为它们定义接口。

但是,如果您有需要 setter 和 getter 的东西,比如 bean 可能,并且还需要在编译类型(而不是像 bean 可能在运行时)插入,并且可能存在多个实现,那么是的,这将需要一个定义 getter 和 setter 的接口。

希望能帮助到你。

于 2010-04-03T22:24:54.340 回答
1

这触及了整个 Getter/Setter 是邪恶的话题,在本网站和其他地方多次提到。

我倾向于在接口中没有访问器,而是使用构造函数参数将协作者添加到实现中。

于 2009-07-15T09:25:10.193 回答
1

某些东西的直接实现是作为 getter 的事实不应该阻止它在需要时出现在接口中。

于 2009-07-15T09:32:24.923 回答
1

我使用了这类接口,例如我们有带有字段 beginDate、endDate 的类。这些字段在许多类中,我有一个用例需要获取不同对象的这些日期,所以我提取了接口并且非常高兴:)

于 2009-07-15T10:24:37.470 回答
0

进一步阅读:Java 框架架构师的实用 API 设计自白(Jaroslav Tulach,2008,Apress)。

于 2009-07-15T09:24:46.327 回答
0

基本上,如果回答“我需要知道 [state, property, whateverThignAMAGit] 的值才能使用它的实例吗?” 那么是的......访问器属于接口。

上面 John 的 List.size() 是需要在接口中定义的 getter 的完美示例

于 2009-07-15T10:26:07.123 回答
0

Getter 用于查询对象的状态——在设计界面时可以避免这种情况。阅读http://www.pragprog.com/articles/tell-dont-ask

于 2009-08-16T19:01:13.073 回答