どういうわけか次のことが可能ですか?
interface Foo<T> {
public void bar(T object);
}
...
public void callBar(Foo<?> foo) {
foo.bar("Hello world!");
}
明らかに、これはタイプ セーフではありません。Foo<?>
この場合、実際にはFoo<String>
.
しかし、通常の「チェックされていない」警告ではなく、実際には次のエラーが表示されます: The method bar(capture#1-of ?) in the type Foo is not applied for the arguments (String)
通常、この例外を必要な警告に変えるためにできるキャストがいくつかありますが、どういうわけか今は見つかりません...
何か考えはありますか ( 「これをしないでください!」以外にお願いします)?
編集:
誰もが「これをしないでください」について話し合いたいと思っているようです。それで、私が解決しようとしている問題全体をできるだけエレガントに説明させてください。
イベントごとに 10 億のインターフェイス タイプを宣言する必要のない柔軟なイベントバス システムを作成しようとしています。
EventBus
次のようなクラスが必要です。
public class EventBus<GroupType, EventType> {
...
public void addHandler(EventHandler<GroupType, EventType, ?> handler, GroupType group, EventType... events) {
// ^ this is the <?> !!!
// add handler to list of handlers for group and requested event types
}
public <Source> void fireEvent(GroupType group, EventType event, Source source) {
// call all handlers registered for group and event type
}
}
インターフェイスEventHandler
は次のようになります。
public interface EventHandler<GroupType, EventType, Source> {
public void onEvent(GroupType group, EventType event, Source source);
}
そうすれば、次のようにイベント ハンドラーを簡単に記述できます。
public class Handler implements EventHandler<Groups, Events, TextBox> {
public void onEvent(Groups group, Events event, TextBox source) {
// Do something with source immediately
}
}
ここでGroups
、 およびEvents
は、可能なイベント タイプを記述する列挙型です。
次に、それらを登録します
addHandler(myHandler, Groups.EDIT_BOXES, Events.VALUE_CHANGED, Events.CLEARED, ...);
そして、私はそれらを呼び出すことができます
fireEvent(Groups.EDIT_BOXES, Events.VALUE_CHANGED, myEditField);
私のコードでは、グループ内のすべてのソースが型であり、作成するすべてのハンドラーで自分の人生を型キャストしたくないことを知っています。そのため、ハンドラーに特定のインターフェイスを実装できるようにしたいのですが、次のようにすべてのハンドラーを記述するのではなく、EventBus からの安全でない型キャスト (一度書いて永遠に隠します) で呼び出します。EDIT_BOXES
TextBox
public class Handler implements EventHandler<Groups, Events> {
public void onEvent(Groups group, Events event, Object source) {
TextBox usableSource = (TextBox) source;
// Do something with usableSource
}
}
また、キャストが間違っていると、プログラムはクラッシュしていずれかの方法で書き込みます。ハンドラーに「instanceof」チェックを入れても、何らかの方法でそれをエラーとしてスローする必要があります。私はそれをエレガントに行うことができますが、実際には問題ではありません。このシナリオのエラーは、修正する必要があるコードのバグであり、ユーザーに適切に通知する必要がある実行時のユーザー エラーではないためです。
さて、私は他のライブラリが完全にタイプセーフなイベント システムを実装しているのを見てきましたが、これには多くの場合、可能なすべてのタイプのイベントとすべての可能なタイプのイベント ハンドラー、場合によってはイベントバス自体の関数に対してもインターフェイスを宣言する必要があります。あなたが私に尋ねると、それは価値があるよりもはるかに苦痛です.
私が達成しようとしていることを実行するための明確な方法を持っている人がいるなら、私はうれしく思います. しかし、それが他の方法で実行可能かどうかはわかりません。