I ran into a sticky problem that I cannot solve with java generics. This is a bit complicated, but I could not come up with a simpler scenario to illustrate the problem ... Like this:
I have a processor class that needs context. There are various types of context; most processors need some kind of abstract context, but others require a certain subclass. Like this:
abstract class AbstractProcessor<C extends Context> { public abstract void process(C context); } class BasicProcessor extends AbstractProcessor<Context> { @Override public void process(Context context) {
Ok, cool: Processors can declare the type of Context they need, and they can assume that the correct type will be passed to process () without casting.
Now I have a Dispatcher class that owns string matching for processors:
class Dispatcher<C extends Context> { Map<String, AbstractProcessor<? super C>> processorMap = new HashMap<String, AbstractProcessor<? super C>>(); public void registerProcessor(String name, AbstractProcessor<? super C> processor) { processorMap.put(name, processor); } public void dispatch(String name, C context) { processorMap.get(name).process(context); } }
Ok, so far so good! I can create a dispatcher for a specific type of Context, and then register a processor package that can expect any abstraction of this type of Context.
Now here's the problem: I want the abstract Context type to own the Dispatcher, and derived Context types should be able to register additional Processors. Here is the closest I can find for a working solution, but it does not work fully:
class Context<C extends Context> { private final Dispatcher<C> dispatcher = new Dispatcher<C>(); public Context() {
The problem is that I need to declare a generic dispatcher in the Context base class, but I want the type variable to refer to a specific derived type for each Context subtype. I don’t see a way to do this without duplicating some code in each subclass of Context (in particular, when creating a Dispatcher and registerProcessor method). Here is what I think I really want:
Dispatcher<MyRealClass> dispatcher = new Dispatcher<MyRealClass>();
Is there a way to declare a generic object type with a SUBCLASS type of a declaring class?
Yes, I can solve this problem with a bit of low-risk casting, so this is basically an academic question ... But I would like to find a solution that just works from top to bottom! You can help? How do you approach this architecture?
UPDATE
Here's the full source, updated to include Andrzej Doyle's suggestion to use <C extends Context<C>> ; it still does not work, because Context<C> != C :
class Context<C extends Context<C>> { private final Dispatcher<C> dispatcher = new Dispatcher<C>(); public Context() {