グローバル定数は、それが...である限り、悪い習慣ではありません。
- ...不変-グローバル、
final
/readonly
可変オブジェクト(JavaArrayList<T>
やC#List<T>
など)への参照は定数ではなく、グローバル状態です。
- ...>1クラスで必要です。定数が必要なクラスが1つだけの場合は、定数をクラスに直接配置します。(警告:DRYとYAGNIのバランスを適切に取ってください。)
Blochは、Effective Javaの「定数インターフェイス」と「定数クラス」の問題を取り上げ、「定数クラス」アプローチを提唱しています。インターフェイスに定数が必要ない理由は、クライアントクラスがそのインターフェイスを「実装」するように誘導するためです(インターフェイス名をプレフィックスとして付けずに定数にアクセスするため)。ただし、そうすべきではありません。インターフェイスは実際にはオブジェクトの機能へのインターフェイスではなく、クラスの外部型に組み込まれたコンパイル時の利便性です。このことを考慮:
interface C { public static final int OMGHAX = 0x539; }
class A implements C { ... }
class B { private A a; }
クラスB
は不必要にに依存するようになりましたC
。A
からの定数を必要としないように変更を実装した場合、外部インターフェイスを壊さずにC
削除することはできません-誰か(おそらく非常に愚かな人ですが、そのような人はたくさんいます)は、参照を通じてオブジェクトを参照する可能性があります!implements C
A
C
定数をクラスに入れ、そのクラスをインスタンス化できないようにすることで、定数クラスが実際にはサブ名前空間として機能することをクライアントに通知します。C#では、クラスをとしてマークしstatic
ます。Javaでは、クラスを作成しfinal
て、到達不能なコンストラクターを指定します。
final class C {
private C() { throw new AssertionError("C is uninstantiable"); }
public static final int OMGHAX = 0x539;
}
Javaでプログラミングし、定数に定数クラス名を付けずに定数が必要な場合は、このimport static
機能を使用できます。
はい、定数を配置するためだけに新しい型を作成することを余儀なくされるのは少し冗長ですが、JavaやC#などの言語では、これを処理する必要があります。定数をどこかに配置する必要があります。最良のオプションは、インスタンス化できないクラスです。