クライアントによって保存されている、クライアントセッション状態のコンテキストでクライアントによって要求されたアクションを処理できる、可能な要求ハンドラーを記述するインターフェイスがあるとします。
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 がインスタンス化または使用される場所ならどこにでも持ち運ばなければならない自重だからです...State
Object
?
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
これにより、実際に何が何であるかを常に指定する必要なく、どこでも呼び出すことができます。しかし、クラス全体に相当する構造はありません (いくつかの推測された一般的な引数) はありますか?