web-dev-qa-db-ja.com

定数のコレクションをクラスまたはインターフェイスに配置する必要がありますか?

静的定数のコレクションがあり、それらがクラスまたはインターフェイス(Java)に配置された場合に、さまざまなプロジェクト間で共有できるように、一元的に宣言したい場合。

過去に私はそれらがほとんどクラスに入れられるのを見たことがありますが、クラスはインスタンス化されないので、インスタンス化されるべきではないので、インターフェイスでより良いかもしれないと思い始めましたが、インターフェイスはどのクラスでも実装されるべきではありません。

public class ErrorCodes {
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";
}

または

public interface ErrorCodes {
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";
}
35
DaveJohnston

それらが強い接続を持っている場合、私はそれらを列挙型に入れます:

_public enum Error {
  ERROR_1("-1", "foo went wrong"),
  ERROR_2("-2", "bar went wrong");

  private final String id;
  private final String message;

  Error(String id, String message) {
    this.id=id;
    this.message=message;
  }

  public String getId() {
    return id;
  }

  public String getMessage() {
    return message;
  }
}
_

利点は、コードに型の安全性を持たせることができ、IDベースのルックアップを簡単に追加できることです(コンストラクターで_HashMap<String,Error>_を作成するか、values()をループするだけです)。

33
Joachim Sauer

一部の人々は、定数インターフェイスをアンチパターンと見なしています( http://en.wikipedia.org/wiki/Constant_interface )。

11

あなたはクラスでそれをするべきです。

インターフェイスは、クラスユーザーがアクセスできる使用可能なメソッド、プロパティなどの説明です。インターフェイスを実装することにより、インターフェイスで宣言されたメンバーがユーザーに使用可能であることを保証します。

一方、クラスはオブジェクトの説明であるか、(あまりにもOO原則...)静的メンバーのプレースホルダー個人的には、いくつかのプロジェクトでSettingsクラスに多数の定数を格納することが非常に役立つと思うので、周りを見回す必要はありません。定義のためのプロジェクト全体。このアプローチもあなたが求めているものだと思います。

7
Tomas Aschan

これは議論されました

インターフェイスに定数が必要ない理由は、クライアントクラスがそのインターフェイスを「実装」するように誘導するためです(インターフェイス名をプレフィックスとして付けずに定数にアクセスするため)。ただし、そうすべきではありません。インターフェイスは実際にはオブジェクトの機能へのインターフェイスではなく、クラスの外部型に組み込まれているコンパイル時の利便性です。

「定数インターフェイス」が非常に便利だった時代がありましたが、それは常に「間違った」ものであり、import staticステートメントがあるので、怠惰でさえそれを使用する言い訳にはなりません。

編集:質問で提示されたシナリオでは、列挙型の方が適切であることに同意する必要があります。

6
gustafc

ここでは、静的インポートの使用を検討する必要があります(クラスで定義された定数をインポートする場合)、または type-safe Enum

From 定数のインターフェース

インターフェイスに定数を配置することは、Javaの初期の頃は一般的な手法でしたが、インターフェイスはオブジェクトによって提供されるサービスを処理する必要があるため、インターフェイスの不快な使用と見なされるようになりました。データ
同様に、クラスで使用される定数は通常、実装の詳細ですが、それらをインターフェースに配置すると、クラスのパブリックAPIに昇格します。

5
VonC

プライベートコンストラクターを使用してクラスに配置する必要があります。

public class ErrorCodes {
    private ErrorCodes() {} // prevents instantiation
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";

}

または、さらに良いことに、タイプセーフ列挙型を使用します。

3
Billy Bob Bain

静的インポートと定数のインターフェイスの組み合わせをお勧めします。

Javaインターフェースに定数フィールド宣言がある場合、これらは暗黙的にpublic、static、finalであることに注意してください(を参照) Java言語仕様、 セクション9. 。)したがって、これらの修飾子はいつでも省略でき、型のみが残り、定数インターフェイスは次のようになります。

public interface Constants {
    int AGE = 0x23;
    String NAME = "Andrew";
    boolean IGNORE = true;
}

もちろん、これはonlyを次のように使用する必要があります。

import static Constants.*;

public Whatever {
    public String method() {
        return String.format("%s is %d%c", NAME, AGE, IGNORE ? '?' : '!');
    }
}

プロダクションコードでこのスタイルを使用しても問題はなく、非常にすっきりとしたコンパクトな定数コレクションにつながり、列挙型では不可能だったさまざまなタイプの定数に対応できるほか、次の場合に拡張できると感じています。列挙型とは異なり、必須です。

誰もが承認するわけではないもう1つの可能性は、親インターフェイスにインターフェイス(または列挙型)をネストして、定数をグループ化できるようにすることです。この :

interface MoreConstants {
    int MAGIC = 0xCAFEBABE;
    interface PROPERTIES {
        String NAME = "name";
    }
    enum ERRORS {
        ON_FIRE, ASLEEP, BROKEN, UNSURE;
    }
}

MoreConstantsインターフェースの静的インポートを想定して、次のようにアクセスします。

if (!PROPERTIES.NAME.equals(value)) {
    return ERRORS.UNSURE;
}

もちろん、これらのインターフェースは決して実装されるべきではありません。これは悪い習慣だと思います。ただし、これを確実にする唯一の方法は、厳密なコードレビューです...

2
grkvlt

定数にインターフェイスを使用することをお勧めします。ただし、定数を使用するためにそのインターフェイスを実装する必要はありません。ただし、以下のように静的インポートを使用します。

package com.data.job.spark;

public interface Constants {

    /** base api url string literal. */
    public static final String BASE_API_URL = "/api/v1";
        /** message string literal. */
    public static final String MESSAGE = "message";

    /** exception string literal. */
    public static final String EXCEPTION = "exception";
}
=================================
import static com.data.job.spark.Constants.EXCEPTION;

@Component("user360ToScyllaDbLoader")
public class TestConstants implements Serializable{


    private static final long serialVersionUID = 1L;
}
1
Dakshin Rajavel

個人的には、上記と同じ理由で定数をクラスで定義する必要があると感じています。特に、一部の開発者は、これらの定数を使用したいクラスにインターフェースを実装することによってこれらの定数を使用しているためです。そのインターフェイスに多くの定数が含まれている場合、そのクラスで使用されていない可能性のある定数の説明が散らばっているため、その特定のクラスのjavadocを確認する必要はありません。

0
Not-The-Mama