Java接口使用指南 - 接口中的getter和setter是不是很糟糕?

时间:2009-07-15 09:15:48

标签: java interface javabeans setter getter

人们如何看待在界面中使用的最佳指南?什么应该和不应该进入界面?

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

我的观点:对于制定者来说可能不是这样,但有时候我认为getter可以放在界面中。这仅仅是为了强制实现类来实现这些getter,以便表明客户端能够调用那些getter来检查某些内容,例如。

11 个答案:

答案 0 :(得分:24)

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

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

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


编辑:正如评论中所述,这在JavaBeans specification第7.1节中已明确说明:

  

因此即使脚本编写者输入   在诸如b.Label = foo之类的东西中   还有一个方法调用   目标对象来设置属性,和   目标对象已满   程序控制。

     

所以属性不仅仅是简单   数据字段,它们实际上可以   计算值。更新可能有   各种程序性副作用。对于   例如,更改bean的背景   颜色属性也可能导致   要重新粉刷新的豆子   色“。


如果假定的暗示 为真,我们也可以直接将属性公开为字段。幸运的是,暗示持有:getters和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
}

或(最好是IMO):

private Size size;

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

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

public Size getSize() {
    return size;
}

这里size属性或高度/宽度属性仅为方便起见 - 但我没有看到这使它们无论如何都无效。

答案 1 :(得分:12)

我认为通常会声明两种类型的接口:

  1. 服务说明。这可能类似于CalculationService。我不认为方法getX应该在这种界面中,当然不是setX。它们非常清楚地暗示了实现细节,这不是这种类型接口的工作。
  2. 数据模型 - 仅用于抽象出系统中数据对象的实现。这些可能用于帮助测试,或者仅仅因为有些像我一样的人记得(例如)使用持久性框架将你绑定到具有特定超类的日子(即,如果你切换,你会选择实现一个接口)你的持久层)。我认为在这种类型的接口中使用JavaBean方法是完全合理的。
  3. 注意:集合类可能适合键入#2

答案 2 :(得分:10)

对于吸气者/制定者来说,没有什么本质上的邪恶。但是:

  1. 我倾向于使我的对象相对于它们包含的字段是不可变的(在第一个实例中)。为什么?我在构建阶段实例化大多数事情。如果我想稍后改变一些东西,那么我放松这些限制。所以我的界面往往包含getter,但不包含setter(还有其他好处 - 特别是线程)。
  2. 我希望我的对象为我做事,而不是相反。因此,当我的一个对象获得了许多getter时,我开始询问该对象是否应该具有更多功能,而不是将其所有数据暴露给其他可以使用的数据。有关详细信息,请参阅this answer
  3. 这些都是指导方针,请注意。

答案 3 :(得分:4)

一般来说,我不认为bean应该有一个接口。 javabean是更一般意义上的接口。接口指定更复杂的外部合同。 javabean的外部合同及其内部表示是相同的。

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

答案 4 :(得分:2)

  

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

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

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

考虑到这一点,在语法和语义上都没有错误 - 在接口中设置了setter和getter。

如果你的应用程序设计得很好并且问题需要你有一个定义setter和getter的接口,为什么不呢。例如,看一下ServletResponse接口。

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

但是如果你有需要setter和getter的东西,就像bean那样,并且还需要在compile-type中插入(不像运行时那样插入bean),并且可能存在多个实现,那么是的,这将需要一个定义getter和setter的接口。

希望它有所帮助。

答案 5 :(得分:1)

这涉及到整个Getter / Setter是一个邪恶的话题,在本网站和其他地方多次解决。

我倾向于不赞成在界面中没有访问器,而是使用构造函数参数向协作者添加协作者。

答案 6 :(得分:1)

直接实现某些东西作为一个吸气剂的事实不应该阻止它在一个接口中,如果需要的话。

答案 7 :(得分:0)

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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

基本上如果答案“我是否需要知道[state,property,whateverThignAMaGit]的价值才能使用它的实例?”那么是......访问者属于界面。

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

答案 10 :(得分:0)

Getters用于查询对象的状态 - 在设计界面时可以真正避免。阅读http://www.pragprog.com/articles/tell-dont-ask