Is the following possible somehow?
interface Foo<T> {
public void bar(T object);
}
...
public void callBar(Foo<?> foo) {
foo.bar("Hello world!");
}
Clearly, this is not type-safe as it is assuming that Foo<?>
in this case actually is a Foo<String>
.
But rather than the usual "unchecked" warning, this actually gives me the following error: The method bar(capture#1-of ?) in the type Foo is not applicable for the arguments (String)
Usually there's some casting I can do to turn this exception into the warning I want, but somehow I can't find one right now...
Any thoughts (other than "don't do this!", please)?
EDIT:
It seems like everyone does want to discuss the "don't do this", so let me explain the entire problem I'm trying to solve as elegantly as possible and then maybe someone has a cleaner way to do this...
I'm trying to write a flexible eventbus system, where I don't need to declare a billion interface types for each event.
I want to have a class EventBus
that looks like this:
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
}
}
where the interface EventHandler
looks like this:
public interface EventHandler<GroupType, EventType, Source> {
public void onEvent(GroupType group, EventType event, Source source);
}
That way, I can simply write my event handlers to look like this:
public class Handler implements EventHandler<Groups, Events, TextBox> {
public void onEvent(Groups group, Events event, TextBox source) {
// Do something with source immediately
}
}
where Groups
and Events
are Enums that describe the possible event types.
Then I register them with
addHandler(myHandler, Groups.EDIT_BOXES, Events.VALUE_CHANGED, Events.CLEARED, ...);
And I can call them with
fireEvent(Groups.EDIT_BOXES, Events.VALUE_CHANGED, myEditField);
In my code, I know that in the group EDIT_BOXES
all sources are of type TextBox
and I don't want to type-cast my life away in every handler I write. That's why I would like to be able to implement the specific interface in the handler, but call it with an unsafe typecast from the EventBus (which I write once and hide forever) rather than having to write all my handlers like this:
public class Handler implements EventHandler<Groups, Events> {
public void onEvent(Groups group, Events event, Object source) {
TextBox usableSource = (TextBox) source;
// Do something with usableSource
}
}
And if the cast is wrong, the program will and should crash and burn either way. Even if I put an "instanceof" check in the handler, I will need to somehow throw that as an error. I can do that elegantly, but it doesn't really matter, since any error in this scenario is a bug in the code that needs to be fixed and not some runtime user-error, which I should gracefully inform the user of.
Now, I've seen other libraries implement a completely type-safe event system, but often this involves having to declare interfaces for every possible type of event and every possible type of event handler and sometimes even for functions on the eventbus itself, which, if you ask me, is WAY more pain than it's worth.
If any of you have a clean way to do what I'm trying to achieve, I'd be stoked. But I'm not sure it's doable any other way.