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


40

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

我看到的好处有:

  • 轻松访问常量:MY_CONSTANT而不是ThatClass.MY_CONSTANT
  • 每个常量仅定义一次

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

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


答案是“用接口定义X?是不好的做法”,因为X等于不是“方法签名”的任何东西,几乎肯定总是“是”。
T. Sar-恢复莫妮卡

Answers:


79

约书亚·布洛赫(Joshua Bloch)在他的《有效的Java》一书中建议不要这样做

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

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


13

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

SOMETIMES常量是实现细节。有时它们不是。像往常一样,工程师需要用他的大脑来决定要做什么,而不要依靠全面的模式或实践。


7

我认为为常量提供接口不是一件好事。

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

以java.awt.Transparency接口为例。它具有OPAQUE,BITMASK和TRANSLUCENT常量,还具有getTransparency()方法。

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


2

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


1
接口是公共合同。常量值是个人关注的问题,公共接口最多应公开其名称。最好留给抽象类。
jwenting 2011年

相关案例:javax.naming.Context,javax.ims.Session以及数百个此类接口...
CMR

2
@jwenting另外,可以公开一个接口"at most expose their names",而不公开这些值吗?
CMR

那取决于我猜的编程语言。如果是Java,则不会。
jwenting 2014年

2

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

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

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


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


1

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

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

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

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


添加更多引用静态导入(1.5)的链接:1. Wikipedia 2. 引用@Justinc的Oracle文档
Abhijeet

1
So when should you use static import? Very sparingly! Only use it when you'd otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Oracle文件
Abhijeet 2015年

1

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

关键是,应在最小可见性和适当抽象级别的规则下引入常量,如其他任何伪像。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.