effective-java-3rd-chinese/35. 使用实例属性替代序数.md
2018-11-24 15:06:35 +08:00

38 lines
2.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 35. 使用实例属性替代序数
  许多枚举通常与单个 `int` 值关联。所有枚举都有一个 `ordinal` 方法,它返回每个枚举常量类型的数值位置。你可能想从序数中派生一个关联的 `int` 值:
```Java
// Abuse of ordinal to derive an associated value - DON'T DO THIS
public enum Ensemble {
SOLO, DUET, TRIO, QUARTET, QUINTET,
SEXTET, SEPTET, OCTET, NONET, DECTET;
public int numberOfMusicians() { return ordinal() + 1; }
}
```
  虽然这个枚举能正常工作,但对于维护来说则是一场噩梦。如果常量被重新排序,`numberOfMusicians` 方法将会中断。 如果你想添加一个与你已经使用的 `int` 值相关的第二个枚举常量,则没有那么好运了。 例如为双四重奏double quartet添加一个常量可能会很好它就像八重奏一样由 8 位演奏家组成,但是没有办法做到这一点。
  此外,如果没有给所有这些 `int` 值添加常量,也不能为某个 `int` 值添加一个常量。例如,假设你想要添加一个常量,表示一个由 12 位演奏家组成的三重四重奏triple quartet。对于由 11 个演奏家组成的合奏曲,并没有标准的术语,因此你不得不为未使用的 `int`11添加一个虚拟常量dummy constant。最多看起来就是有些不好看。如果许多 `int` 值是未使用的,则是不切实际的。
  幸运的是,这些问题有一个简单的解决方案。 **永远不要从枚举的序号中得出与它相关的值; 请将其保存在实例属性中:**
```Java
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8),
NONET(9), DECTET(10), TRIPLE_QUARTET(12);
private final int numberOfMusicians;
Ensemble(int size) { this.numberOfMusicians = size; }
public int numberOfMusicians() { return numberOfMusicians; }
}
```
  枚举规范对此 `ordinal` 方法说道:“大多数程序员对这种方法没有用处。 它被设计用于基于枚举的通用数据结构,如 `EnumSet``EnumMap`。“除非你在编写这样数据结构的代码,否则最好避免使用 `ordinal` 方法。