0

JAVAコードERequestTypesに列挙型があります。列挙型には20を超える要素が含まれています。すべての要素は、JAVAコード内の関数の名前です。今、私は書く代わりに次のことをしたいと思いますswitch(ERequestTypes) case、そしてこのように関数を呼び出す場合:

switch(ERequestTypes a) {
    case ERequestTypes.Initialize:
        Initialize();
    case ERequestTypes.Uninitialize:
        Uninitialize();
}

一行でやりたいです。列挙型のすべての関数は同じ引数を持ち、同じint値を返します。どうすればそれができますか?C ++などのように、関数のポインタを列挙型に保持することができます。助けてください !

class CRequestValue {
    /**
     * Constructor.
     * 
     * @param aName - Name of the request.
     * @param aCode - Code of the request.
     */
    public CRequestValue(String aName, int aCode) {
        this.mName = aName;
        this.mCode = aCode;
    }

    private String mName;
    private int    mCode;

    public String GetName() {
        return this.mName;
    }

    public int GetCode() {
        return this.mCode;
    }

} /* class CRequestValue **/

enum ERequestTypes
{
    Initialize(new CRequestValue("Initialize", 0)),
    Uninitialize(new CRequestValue("Uninitialize", 1)),
    GetDeviceInfoList(new CRequestValue("GetDeviceInfoList", 2)),
    GetDeviceInfo(new CRequestValue("GetDeviceInfo", 3));

    private CRequestValue mRequestValue;

    private ERequestTypes(CRequestValue aRequestValue) {
        this.mRequestValue = aRequestValue;
    }

    public String GetName() {
        return this.mRequestValue.GetName();
    }

    public int GetCode() {
        return this.mRequestValue.GetCode();
    }

} /* enum ERequestTypes **/
4

3 に答える 3

3

あなたの目標が何であるかはわかりませんが、たとえば、スイッチブロックの代わりにポリモーフィズムを使用できます。

interface Invokable {
    int init(Object arg);
    int uninit(Object arg);
}

enum Request {
    INIT() {
        @Override
        public int invoke(Invokable invokable, Object arg) {
            return invokable.init(arg);
        }
    },
    UNINIT() {
        @Override
        public int invoke(Invokable invokable, Object arg) {
            return invokable.uninit(arg);
        }
    },
    ;
    public abstract int invoke(Invokable invokable, Object arg);
}


Invokable i = ....;
Object arg = ....;
Request r = Request.INIT;
r.invoke(i, arg); // should invoke Invokable.init(arg);
r = Request.UNINIT;
r.invoke(i, arg); // should invoke Invokable.uninit(arg);
于 2012-06-29T15:09:04.427 に答える
2

あなたは反射を探しています。

ErequestTypes a = <init>;
Object o = Class.forName(<your class name>).getMethod(a.getName(), <argtype>.class).invoke(<instance of your class, or null if static method>, <arg>);

メソッドがどのクラスにあるかをすでに知っている場合は、Class.forNameは必要ないことに注意してください。

于 2012-06-29T14:58:44.700 に答える
0

Pavelが言及したポリモーフィズムを使用することもできますが、別の解決策があります。実際には列挙型はまったく必要ありません。

各関数を独自のオブジェクトにし、列挙型と同じようにそれらのオブジェクトのインスタンスを渡す/使用するのは非常に簡単です。

匿名内部クラスを使用する解決策もいくつかありますが(オブジェクトインスタンスにそれらをアタッチしてそれらのインスタンスを渡す)、それは一般に、個別のオブジェクトを作成するほど再利用可能ではないと思います。

ここにいくつかの偽のコードがあります:

public void MainClass {
    private final Runnable init=new Runnable {
        run() {
            // Initialize the system
        }
    }
    private final Runnable uninit = new Runnable() {
        run() {
            // Uninitialize the system
        }
    }

public someMethod() {

    // At this point you can treat the instances as you would any variable...
    Runnable nextOperation = init;

    // and executing whichever one you have is as simple as:
    nextOperation.run();

(列挙型のように)「型安全性」が必要な場合は、Runnableを拡張せずに、runnableを拡張する新しいクラスを作成してから、そのクラスを拡張します。

これらは「内部クラス」(別のクラスのコンテキスト内で定義)であるため、すべてのクラスのメンバー変数にアクセスして変更できるため、スタンドアロンクラスよりも独立したメソッドのようになります。

最後に、各クラスは匿名でインラインで定義されているため、列挙型と同じくらい「重複」を作成するのが難しいことに注意してください。したがって、通常、列挙型として正確に扱うことができます(たとえば、.equals()の代わりに「==」を使用します)。

于 2012-06-29T15:41:45.677 に答える