×

消息

EU e-Privacy Directive

This website uses cookies to manage authentication, navigation, and other functions. By using our website, you agree that we can place these types of cookies on your device.

View e-Privacy Directive Documents

You have declined cookies. This decision can be reversed.

接口只用来定义类型

如果一个类实现了某个接口,那么这个接口类型可以成为指向该类对象的引用。因此类与接口之间的"实现"关系,应该能使用户通过接口了解对象的行为。除了这个场景以外,定义接口都是不合适的。违背上述原则的一个反例是常量接口,这样的接口不定义任何方法,仅含有静态final属性,每一个属性都被开放为常量。用户类通过实现这些接口来避免使用常量全名。比如下面的例子:

// Constant interface antipattern - do not use!
public interface PhysicalConstants {
	// Avogadro's number (1/mol)
	static final double AVOGADROS_NUMBER = 6.02214199e23;
	// Boltzmann constant (J/K)
	static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
	// Mass of the electron (kg)
	static final double ELECTRON_MASS = 9.10938188e-31;
}

常量接口是对接口机制的滥用。因为类对常量的使用是一种实现细节,而常量接口会使这些实现细节被泄露到开放的API中。在后续新版本中这些接口必须一直被维护,以保证向下兼容性。一旦某个类实现了常量接口,它所有子类的名空间都会受到这些常量的污染。

Java标准库中有几个常量接口,比如java.io.ObjectStreamConstants。这些接口应该被视为设计缺陷,开发者不应该模仿它们。

正确开放常量的方式有好几种。如果常量与某个类或接口紧密相关,那么应该被直接加入相应的类或接口中。比如,对于封装的数据基本类型Integer或者Double,可以声明MIN_VALUE和MAX_VALUE常量。如果常量可被视作枚举类型的成员,那么他们应该被定义为枚举类型(enum type)。否则,常量应该通过不可实例化的工具类(item 4)来定义。下面是一个正确定义上述PhysicalConstants的例子:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
	private PhysicalConstants() { } // Prevents instantiation
	public static final double AVOGADROS_NUMBER = 6.02214199e23;
	public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
	public static final double ELECTRON_MASS = 9.10938188e-31;
}

通常工具类要求用户使用常量全名,比如:PhysicalConstants.AVOGADROS_NUMBER。如果使用频繁,可以通过静态导入(static import)来简化代码:

// Use of static import to avoid qualifying constants
import static com.effectivejava.science.PhysicalConstants.*;
public class Test {
	double atoms(double mols) {
	return AVOGADROS_NUMBER * mols;
}
...
// Many more uses of PhysicalConstants justify static import
}

总之,接口必须用来定义类型,而不能用来定义常量。

提交评论


安全码
刷新