it-swarm.cn

具有定义常量的接口是不好的做法吗?

我正在用Java编写一组junit测试类。有几个常量,例如在不同的测试类中需要的字符串。我正在考虑一个定义它们的接口,每个测试类都将实现它。

我看到的好处有:

  • 易于访问常量:MY_CONSTANT 代替 ThatClass.MY_CONSTANT
  • 每个常量仅定义一次

这种方法是好的还是坏的做法?我觉得这样做有点像在滥用接口的概念。

您通常可以回答有关接口/常量的问题,也可以回答有关单元测试的问题(如果有什么特别之处)。

45
FabianB

约书亚·布洛赫(Joshua Bloch)在他的著作Effective Java中建议不要这样做:

类内部使用一些常量是一个实现细节。实现常量接口会导致此实现细节泄漏到类的导出API中。对类的用户而言,该类实现一个常量接口并不重要。实际上,这甚至可能使他们感到困惑。更糟糕的是,它表示一种承诺:如果在将来的版本中对该类进行了修改,使其不再需要使用常量,则它仍必须实现该接口以确保二进制兼容性。

您可以通过定义常量的普通类获得相同的效果,然后使用import static com.example.Constants.*;

88
matt

在我们的例子中,我们这样做是因为常量的值表示需要服务实现提供的最终状态的约定。将这些常量放在接口中可将最终状态指定为合同的一部分,并且如果接口的任何实现未使用它们,则将无法完成其工作。

SOMETIMES常量是实现细节。有时它们不是。像往常一样,工程师需要动脑筋来决定要做什么,而不要依靠清扫模式或实践。

14
user144901

我认为拥有常量的接口并不是一件好事。

但是,如果定义行为的接口(实现类的方法应实现)具有常量,则可以。如果它“向API泄漏了一些实现者的细节”,那是因为应该这样做。他们还泄漏了实现者实现.foo().bar()方法。

以_Java.awt.Transparency_接口为例。它具有OPAQUEBITMASKTRANSLUCENT常量,但也具有.getTransparency()方法。

如果设计人员将这些常量放在那里,那是因为他/她认为它会足够稳定以成为接口的一部分,就像.getTransparency()一样。

6
Tulains Córdova

我工作过的一家公司大量使用了进口的接口1个 常数。我觉得没有什么害处。

您应该问自己的问题是命名空间对您来说有多重要?就常量而言,这实际上就是一个类所要做的全部。如果您有数千个常量,则可能不希望所有这些常量始终可用。

关于接口的最酷的事情是,它为您提供了以任何一种方式工作的好处-引入所需的所有名称空间,或者不输入任何名称空间(并使用MyInterface.CONSTANT显式访问它们)。与import static MyInterface.*几乎相同,但更为明显。


1:如果您不熟悉Java,则不是_import关键字,而是通过implements MyConstantsInterface引入

2
Nicole

认为这是在按合同设计占主导地位的地方最受欢迎的观点。
接口是合同。在接口中放置常量意味着遵守合同的每个类都同意该常量标识的值/概念。

2
CMR

不,这不是一般的坏习惯。

关键是,应在最小可见性和适当抽象级别的规则下引入常量,就像其他任何人工制品一样。

仅因为可以使用语法才是真正的问题。

1
oopexpert

我来自主要受“ Ada方式”和“ .Net方式”影响的背景。我会说不,在接口中声明常量可能不是最好的。从技术上讲,C#中不允许使用。

我之所以拒绝的原因是,接口是一种定义行为而不是状态或结构的契约形式。常数表示某种状态(原始)或状态的某种方面(复合或聚合)。

我很欣赏将默认值和预定义值提供给实现该接口的每个人的冲动,但是也许最好在抽象或值对象或模板中更好地描述默认状态,其中默认值至少具有最小的上下文。

有关更多技术指南,请下载:download.Oracle.com/javase/1.5.0/docs/guide/language/static-import.html

1
JustinC