2

クライアントによって保存されている、クライアントセッション状態のコンテキストでクライアントによって要求されたアクションを処理できる、可能な要求ハンドラーを記述するインターフェイスがあるとします。

public interface RequestHandler<State> {
    // Perform action in the context of currentState and return updated state
    public State request(State currentState, String action);
}

RequestHandler の実装を簡単にするためにState、必要なすべてのクライアント セッション データをカプセル化するジェネリック型を追加しました。

さて、単純なクライアントは次のようになります。

public class Client {
    private final RequestHandler<?> handler;
    private Object state;

    Client(RequestHandler<?> handler) {
        // Initialize the RequestHandler to use for "go"-requests
        this.handler = handler;
        // Initialize our client state to "null"
        this.state   = null;
    }

    public void go() {
        // Execute "go"-request in current state and update state
        state = handler.request(state, "go");  // <= this is an error (see below)
    }
}

作成中に が提供され、RequestHandler後でそれを使用して「go」リクエストを実行します。stateまた、プライベート変数での現在のセッション状態の格納も管理します。

ここで、クライアントはセッション状態が実際に内部でどのように見えるかを心配する必要がないためRequestHandler<?>、示されているように使用したいと思います。しかし、残念ながら、これにより次のstate = handler.request...行でエラーが発生します。

RequestHandler 型のメソッド request(capture#3-of ?, String) は、引数 (Object, String) には適用されません。

問題のある行を次のように変更するだけで問題はありますか:

state = ((RequestHandler<Object>) handler).request(state, "go");

(これにより、エラーが「チェックされていないキャスト」警告に変わります)

明らかに、このようにしてstate-object の型チェックを緩めますが、 がClientそれを に設定するnullか、 によって返されるものだけであれば、RequestHandler問題はないはずですよね?

同様にパラメータ化Clientして、代わりにどこでも使用することもClient<State>できます。しかし、これは避けたいと思います。なぜなら、(私の意見では)この場合、 a がインスタンス化または使用される場所ならどこにでも持ち運ばなければならない自重だからです...StateObject?Client

にキャストstateする方法はありません(?)よね?

アップデート:

すべてがクラスではなく単一のメソッド内で発生している場合、この問題に対する美しい解決策があります。

public <State> void go(RequestHandler<State> handler) {
    State state = null;
    state = handler.request(state, "go");
    state = handler.request(state, "go again");
    state = handler.request(state, "go one more time");
}

Stateこれにより、実際に何が何であるかを常に指定する必要なく、どこでも呼び出すことができます。しかし、クラス全体に相当する構造はありません (いくつかの推測された一般的な引数) はありますか?

4

2 に答える 2

0

あなたの意図は、クライアントがインターフェイスRequestHandlerに準拠したさまざまなオブジェクトを消費して返す sを定義できるようにすることです。Stateその場合、クライアントが使用している特定のStateタイプを指定できるように、次のようにインターフェイスを定義する必要があります。

public interface RequestHandler<StateType> {
    // Perform action in the context of currentState and return updated state
    public StateType request(StateType currentState, String action);
}

クラスが (非技術的な意味で) ジェネリックであることを意図している場合Clientは、サブクラスまたは独自のクライアントがStateオブジェクトの型を指定できるようにすることで、(技術的な意味で) ジェネリックでもある必要があります。

public class Client<StateType> {
    private StateType state;
    ...
}

既存のコードの問題は、絶対ワイルドカードに含まれる情報がまったくないことです。ワイルドカードが戻り値の型を表す場合、Object有用な動作を持たない class のオブジェクトを取得している可能性があり、引数の型として、基本的にクライアントが任意のオブジェクトを提供することを期待できることを意味します。特定のクラスですが、どちらを言っていませんでした。

于 2013-08-17T04:42:39.203 に答える