1. ホーム
  2. java

[解決済み] 定数」を共有するためのjavaの静的フィールドを持つインターフェース

2022-09-19 13:36:04

質問

Javaを始めるためにオープンソースのJavaプロジェクトを見ていますが、それらの多くがある種の「定数」インタフェースを持っていることに気づきました。

たとえば processing.org というインタフェースがあり PConstants.java というインタフェースがあり、他のほとんどのコアクラスはこのインタフェースを実装しています。このインタフェースは静的メンバで埋め尽くされています。このアプローチには理由があるのでしょうか、それともバッドプラクティスと考えられているのでしょうか?なぜ列挙型を使用しないのでしょうか? を使用しないのでしょうか? または静的なクラスを使用しないのですか?

ある種の擬似的な「グローバル変数」を許容するためにインターフェイスを使用するのはおかしいと思います。

public interface PConstants {

  // LOTS OF static fields...

  static public final int SHINE = 31;

  // emissive (by default kept black)
  static public final int ER = 32;
  static public final int EG = 33;
  static public final int EB = 34;

  // has this vertex been lit yet
  static public final int BEEN_LIT = 35;

  static public final int VERTEX_FIELD_COUNT = 36;


  // renderers known to processing.core

  static final String P2D    = "processing.core.PGraphics2D";
  static final String P3D    = "processing.core.PGraphics3D";
  static final String JAVA2D = "processing.core.PGraphicsJava2D";
  static final String OPENGL = "processing.opengl.PGraphicsOpenGL";
  static final String PDF    = "processing.pdf.PGraphicsPDF";
  static final String DXF    = "processing.dxf.RawDXF";


  // platform IDs for PApplet.platform

  static final int OTHER   = 0;
  static final int WINDOWS = 1;
  static final int MACOSX  = 2;
  static final int LINUX   = 3;

  static final String[] platformNames = {
    "other", "windows", "macosx", "linux"
  };

  // and on and on

}

どのように解決するのですか?

一般的にバッドプラクティスと考えられています。 問題は、定数が実装クラスのパブリックなインターフェイスの一部であることです。 つまり、実装クラスは、内部で必要な値であっても、その値をすべて外部のクラスに公開していることになります。 定数はコードの至る所に散らばっています。 例えば SwingConstants インターフェースで、これは数十のクラスによって実装され、それらはすべて"re-export"されます。 すべて の定数 (使用しない定数も) を自分自身のものとして再エクスポートします。

しかし、私の言葉をそのまま鵜呑みにしないでください。 Josh Bloch も言っています。 は悪いことだと言っています。

<ブロッククオート

定型インターフェイスパターンは、インターフェイスの使い方が悪い。 クラスが内部でいくつかの定数を使用することは、実装の詳細です。定数インターフェースを実装すると、この実装の詳細がクラスのエクスポートされたAPIに漏れることになります。クラスが定数インターフェイスを実装していることは、そのクラスのユーザーにとって何の影響もありません。むしろ、ユーザーを混乱させるかもしれません。さらに悪いことに、これは約束事を意味します。将来のリリースでクラスが修正されて定数を使う必要がなくなったとしても、 バイナリ互換性を確保するためにそのインターフェイスを実装しなければならないのです。最終的でないクラスが定数インターフェイスを実装する場合、そのすべてのサブクラスはインターフェイス内の定数によって名前空間を汚染されることになります。

enumはより良いアプローチかもしれません。 または、インスタンス化できないクラスの public static フィールドとして定数を配置することもできます。 これにより、別のクラスが自身のAPIを汚染することなく、定数にアクセスすることができます。