なぜ

2012-04-10 4 views
4

延び>を私は、Java 1.5で定義されている私はこのクラスから延びて実装することができない次のような問題(java.langパッケージ) なぜ

public abstract class Enum<E extends Enum<E>> {... 
}.. 

つまずい列挙から延在しません私が持っている問題は、異なる序数の値を持つ独自の列挙型を作成することです。私はgetCode()などのような序数の別の名前を使用して実装したくないので、私は上記のクラスを拡張する方法を行くことができると思った。

public final class XYZ extends Enum<XYZ> { //Does not work. 
    // 
    A("A", 1), 
    B("B", 7); 
    . 
} 

私は、私は次の操作を行うことができることを知っている:

public enum NEWEnum { 
    A(1), 
    B(7); 

    private int code; 
    private NEWEnum(int code) { 
    this.code = code; 
    } 
    public int getCode() { 
    return this.code; 
    } 
} 

私が代わりに)通常の列挙型のような順序で、ネーミング・()と名前を(持っていることを好むだろう。

+0

@RayToal私は、序数と名前が最終的なことを知っています。問題はなぜ私が上記のEnumクラスから拡張できないのかということです。拡張可能なのは 'name'と' ordinal'のパラメータを持つprotectedコンストラクタを呼び出すことができるはずです。 – khmarbaise

答えて

5

Enumのように拡張することはできません。これはコンパイラ、またはランタイムに組み込まれています(どちらが確実かはわかりません)。

しかし、間違った問題を解決しようとしているようです。 enum値の序数には何の機能的な意味もないと考えられます。あなたがそれを与えるとすぐ、それは 'Ordinal'とは違う名前になるはずです。 2番目のコードスニペットは、最初のスニペットよりはるかに優れています。

通常、序数に頼るのは悪い習慣です。おそらく最初に露出されていたはずはありません。あなたが信頼できる唯一のものは、名前とあなたが割り当てた任意の価値です。

フィールドに「ordinal」という名前を付けることが重要な場合は、typesafe enum pattern (item 21)を使用してください。Enumはその実装です。

+0

私はordinal()に頼るのは悪い習慣だと知っていますが、私にはレガシーコードがあり、それに対処しなければなりません。だから私はenumパターンに行かなければならない。 – khmarbaise

4

Enumはコンパイラによって特別な扱いを受け、EnumSetのようなクラスはこの処理に基づいて前提条件を作成します。 ordinal()name()のようなEnumメソッドの動作は厳密に定義されており、この動作を複製するためにそれらを実装することは理にかなっていません。また、enum値を宣言する構文は、enumでのみ有効で、classでコンパイルされません。

自分でordinal()を使用しないでください。問題に合わせて定義することは意味がありません。

+0

私はordinal()もnew()newも実装したくありません。私は不可能と思われる抽象的な列挙型クラスから拡張することはできません。 ordinal()の問題は、互換性がなければならない従来のコードがあることです。私はordinal()を取り除こうとしませんでしたが、現在私はチャンスがありません。 – khmarbaise

+0

@khmarbaise javaで具体的なordinal()値を取得する唯一の方法は、enum値をソートし、フィラー値を追加することです(最初の値0、1、...)。 )。他の唯一の方法は、コンパイル後に結果のバイトコードをASMやBCELなどで変更することです。 – josefx

1

Enumクラスは、Enum言語機能の実装に使用されるため、Javaでは特別です。したがって、Javaの他のクラスと同様のクラスではなく、より特別なもの(Stringのように、+演算子がオーバーロードされている、またはボックス化されたクラスのように)。これらの機能を動作させるためには、enumのために特別な要件が必要です(私は連続した序文と同じです)。したがって、Java言語仕様explicitly forbidsは、Enumクラスから手動で継承されています。

0

列挙型は、言語コアと特殊用途で特別な意味を持ちます。したがって、通常のクラスでは不可能なswitchステートメントでそれらを使用することができます。

0

たとえば、明示的に実装する場合、コンストラクタで "name"と "ordinal"のプロパティを初期化する必要はありません。後でNPEが発生する可能性があります。