9

ご存知かもしれませんが、Enum が 1 のインスタンスでシングルトンを宣言する人もいます。これは、JVM が処理する並行性の問題のない単一のインスタンスが常に存在することを保証するためです...

では、複数のインスタンスを持つ Enum はどうでしょうか? Enum のようなものは、共通のインターフェースを共有するシングルトンの一種の順序付けられたセットであると言えますか? なんで?

public enum EnumPriceType {

    WITH_TAXES {
        @Override
        public float getPrice(float input) {
            return input*1.20f;
        }
        public String getFormattedPrice(float input) {
            return input*1.20f + " €";
        }
        },

    WITHOUT_TAXES {
        @Override
        public float getPrice(float input) {
            return input;
        }
    },
    ;

    public abstract float getPrice(float input);

    public static void main(String[] args) {
        WITH_TAXES.getFormattedPrice(33f);
    }

}

このコードでは、なぜこれが機能しないのか: WITH_TAXES.getFormattedPrice(33f); 共通インターフェイスを通過しないと呼び出すことができない場合、パブリック メソッドを宣言する意味は何ですか? これが、列挙型のインスタンスの 1 つだけに対してインターフェイスを宣言できる構文が表示されない理由だと思います。


編集:

enum インスタンスは特別な種類の匿名クラスのようです。したがって、そのメソッドを呼び出すことができない理由を理解しています。

私の質問はちょっと関連しています:匿名クラスがインターフェイスを実装できないのはなぜですか (既に実装されている可能性のあるインターフェイスに加えて!)

なぜそれができないのか、私は完全に理解しています:

Vehicle veh = new Vehicle() {
    public String getName() {
        return "toto";
    }
};
veh.getName();

(ここの getName はオーバーライドではありません)

なぜ私が理解できないのは、匿名クラスでそれができない理由です:

Runnable veh = new Vehicle() implements Runnable {
    @Override
    public void run() {
        System.out.println("i run!");
    }
};
veh.run();

または、同じ結果になるもの。考えてみてください。匿名クラスを使用しない場合は、 Vehicle クラスを完全に拡張して、そのサブクラスに必要な他のインターフェイスを実装させることができます...

WITH_TAXES は実際の EnumPriceType ではなく、独自のインターフェイスを備えた EnumPriceType のサブクラスであるため、可能な場合はタイプセーフな方法で WITH_TAXES.getFormattedPrice(33f) を呼び出すことができると確信しています。ハードコーディングされた WITH_TAXES を使用して WITH_TAXES.getFormattedPrice(33f) を呼び出すと、コンパイル時にどの EnumPriceType 子を呼び出しているかがわかります。

だから私の質問は:これが不可能な理由はありますか? それともまだやってないだけ?

4

3 に答える 3

11

あなたの列挙型は、次の通常のクラスと同等です (実際、これはほとんどコンパイラが変換するものです)。

public abstract class EnumPriceType {

    public static final EnumPriceType WITH_TAXES = new EnumPriceType() {
        //getPrice() {...}
        //getFormattedPrice() {...}
    };

    public static final EnumPriceType WITHOUT_TAXES = new EnumPriceType() {
        //getPrice() {...}
    };

    public abstract float getPrice(float input);

    public static void main(String[] args) {
        WITH_TAXES.getFormattedPrice(33f);
    }
}

このgetFormattedPrice()メソッドは抽象型では使用できないため、メイン メソッドから呼び出すことはできません。ローカル変数を使用するようにメイン メソッドを書き換えるとどうなるかを考えてみましょう。

public static void main(String[] args) {
    EnumPriceType foo = EnumPriceType.WITH_TAXES;
    foo.getFormattedPrice(33f);
}

これはgetFormattedPrice()、基本クラスで使用できないため、コンパイルされません。WITH_TAXESインスタンスは の無名サブクラスであるためEnumPriceType、ローカル変数をメソッドが表示される型に定義するgetFormattedPrice()方法はありません。

メタ観察として、これは Java などの強く型付けされた言語と Ruby などの「ダック型付け」言語との間の重要な違いです。Ruby は、変数getFormattedPrice()に保持されているオブジェクトの型に関係なく、たまたまそこにメソッドがあれば喜んで呼び出します。foo

enum別のメタ観察として、同じの異なる定数が異なるセットメソッドを持つことはあまり意味がありません。必要なすべてを基本列挙型の抽象 (または具象) メソッドとして配置できない場合は、問題を解決するために間違ったツールを使用している可能性があります。

于 2011-09-29T15:45:44.023 に答える
2

追加

       public String getFormattedPrice(float input) {
        return input + " €";
    }

デフォルトの実装としてオーバーライドの外側。(の宣言の隣getPrice)そして、あなたは行ってもいいです。

全員が実装する必要があるものを定義するために、列挙型にインターフェイスを実装させることもできます。

于 2011-09-29T15:43:29.127 に答える
0

では、複数のインスタンスを持つ Enum はどうでしょうか?

そのようなことはありません。あなたの例はそれを示していません。複数の値を持つ Enum があります。それらはすべてシングルトンです。

于 2011-09-29T23:43:48.287 に答える