2012-02-27 9 views
1

子クラスが別のタイプの子クラスを宣言するように強制する簡単な方法を見つけるために、頭脳を絞っています。例えば、私は子クラスが特定の内部クラスを宣言するようにする方法

public final class MessageType1 extends MessageType { 
    public static final class Subtypes extends MessageSubtypes { 
     public static int SOME_SUBTYPE = 1; 
    } 
} 


public final class MessageType2 extends MessageType { 
    public static final class Subtypes extends MessageSubtypes { 
     public static int ANOTHER_SUBTYPE = 1; 
    } 
} 

public abstract class MessageType { 
    public static abstract class MessageSubtypes { 
     public static int ALL_SUBTYPES = 0; 
    } 
} 

を持っているのMessageTypeのすべての子供がMessageSubtypesの独自のバージョンを作成し、それサブタイプに名前を付けるために持っていることを確認する方法はありますか?

または、間違ったサークルで回転している可能性があります。これを行うには、より良い方法があります。基本的には、すべてのメッセージタイプに独自のサブタイプがあり、各サブタイプに値が0のALLというメンバーがあることを確認したいだけです。サブタイプなしでMessageTypeを作成するのはコンパイルしないでください少なくとも使用可能ではないはずです。発生した場合は例外をスローします。

+4

私はこれらのことを行うことはできないと思います。あなたが実際にやろうとしていることを教えてください。 –

+0

私は基本的に非常に小さなpub/subエンジンを使用する複数のクラスの通信ブリッジを作成しています。私はトピックとサブトピックの組み合わせで人々を購読させたいと思っています。すべてのトピックはサブトピックの集合を定義する必要があり、すべてのサブトピックはALLという名前のメンバーを含む必要があります。 –

答えて

6

特定の内部クラスを宣言するように強制する方法を教えてください。

できません。

最も可能なことは、サブタイプが実装する必要があるabstractメソッドを宣言することです。あなたの場合、メソッドabstract Set<MessageSubtype> getSubtypes()を宣言することができます。


名前を単数形に変更しました。また、enumをサブタイプとしてclassよりも使用するほうがよいでしょう。列挙型はで、の固定を表すように最適です。これはコンパイル時に既知の型指定値のセットです。


基本的に私はちょうど私のメッセージタイプのすべてがユニークなサブタイプの独自のセットを持っていることと、各サブタイプは、その値が0でサブタイプなしのMessageTypeを作成しているALLと呼ばれる部材を有することを確実にしたいですよコンパイルすべきではありませんが、それが可能でない場合、少なくとも使用可能ではないはずです。発生した場合は例外をスローします。

あなたは実装に関してあまりにも多くのことを考えており、コードが公開するAPIについては十分ではありません。私はかなり中級レベルのJavaプログラマが、ある時点でこのようなことをしようとしていると思います(私は確かに持っています!)。 について、コードのコンシューマにを使用するためのインタフェースを提供すると考えてください。

+0

私は自分の消費者ですが、他にもあります。私はインターフェイスを持つことはできません。 –

1

スーパークラスは、サブクラス化されているかどうか、どのようにしてサブクラス化されるか分からないと思います。

列挙型を作成し、getメソッドでその型の値を返すことができます。サブクラスが列挙型を変更して独自の型を追加する必要があることは明らかです。

大きな質問は、なぜこれが必要だと思いますか?クラス名は型に関する十分な情報であるはずですか?多形性と動的バインディングの目的を破るデザインはありませんか?

+0

最終結果(独自のサブタイプを持つ最上位のメッセージタイプ)が必要です。それを行うより良い方法があれば私はすべての耳です。 :) –

+0

多態性と仮想的な方法が私の好みですが、おそらく私はあなたの要件を本当に理解していません。 – duffymo

+0

あなたは何を意味するの例を挙げることができますか? .Subtype。<特定のサブタイプ>のようなステートメント、または特にOrderMessage.Subtype.ORDER_OPENEDのようなステートメントを許可しない場合、私のいる状況にはあまり役に立ちません。それ。私の主な関心事は、すべてのサブタイプがその中にALLを持たなければならないということですが、私はクラス構造を通してそれを強制しようとしているのです。その効果にコメントを付けて、人々がそれに従わずに誰かがそのサブタイプからALLを取得しようとしたときにテストを失敗させる方が良いかもしれません。 –

1

基底クラスのコンストラクタにチェックを入れてください:

class BaseClass { 
    public BaseClass() { 
    assert isValidSubclass() : getClass() + " does not contain a suitable inner class"; 
    ... 
    } 

    private boolean isValidSubclass() { 
    Class<?> cl = getClass(); 
    // Maybe cache the test results in a static thread-safe table. 
    for (Class<?> innerClass : cl.getDeclaredClasses()) { 
     if (/* is suitable according to your criteria*/) { return true; } 
    } 
    return false; 
    } 
} 

限り、あなたは有効にアサーションを使用してテストを実行するように、彼らはフェイルファストために、誰かがのインスタンスを構築しようとする最初の時間を引き起こすこと適切な内部クラスを宣言していないサブクラスです。

+0

ユニットテスト構造の外でそれを強制する方法はありますか?人々が作成するすべてのメッセージタイプに対してテストを書くことを保証できないからです。 –

+0

@ JamesMcMurrayの場合、 'assert cond:message'を' if(!cond){新しいAssertionError(メッセージ)をスローする; } ' –

-1

ネストしたクラスはポリモフィズムに参加しません(フィールドと同じように)ので、一般的に不適切なアプローチになります。 Pythonのようなより動的な言語は、あなたが達成しようとしているものにもっと適しているかもしれません。

ただし、これらのサブタイプのの機能について説明できますか?

class MessageType { 
    public abstract MessageSubtype[] getSubtypes(); // to enumerate them 
    public instantiateSubType(<some kind of type discriminator>); // basically a factory function. 
} 

あなたは私が物事をoverthinkingてることを考え始めていますAbstract factory pattern

+0

上記の最初の答えでLouis Wassermanへの返答を見てください。 –

0

を見てみたいことがあり、ちょうどおく必要があります。おそらくこのようなインターフェース/抽象クラスを定義する方が良いだろうそれは簡単です。私の目標は誰もがALLを持つように強制することですが、ある日はすべてのメッセージの購読を許可しないでください。私は物事を簡略化することを考えています:

public abstract class MessageType { 

    protected static class BaseMessageSubtype { 
     public static int ALL = 0; 
    } 

} 

public class OrderMessageType extends MessageType { 

    public static class MessageSubtype extends BaseMessageSubtype { 
     public static int SETTLED = ALL + 1; 
     public static int OPENED = ALL + 2; 
     public static int CLOSED = ALL + 3; 
     public static int VOIDED = ALL + 4; 
     public static int CHANGED = ALL + 5; 
    } 

} 

.Subtypeを使ってもコールは行われます。もし誰かが本当に彼らができるすべてを拒否したいならば。私はすべての型がSubtypeクラスを持つ必要性を強制することはできませんが、それは問題ではないかもしれません。誰かが最終的にそのサブタイプの整数値を持つメッセージタイプを参照できる限り、私たちは大丈夫です。誰かが0であるALLを上書きしてしまい、偶然にメッセージが多すぎる可能性がありますが、プロジェクトは今のところ完全に内部的なので、すぐには起こりそうもありません。

関連する問題