I have a class InteractiveChart that wraps a Chart (interface) and adds interactivity to it by mapping user interactions to setter calls on Chart.
1) Because different subclasses of Chart can have different 'extra' capabilities I want to have a getter in the wrapping class that returns the wrapped Chart (without needing to do an unchecked cast!). The only way I know to do this is by having a generic parameter on the wrapping class.
2) This wrapping class is also meant to be used in NetBeans' GUI Builder, which has the constraint that it requires an empty constructor. However the runtime type of the generic parameter is determined by the code instantiating the it, and I have no control over how NetBeans instantiates it. In this case I want it to wrap a SimpleChart and if the user wants to wrap something else, they'd have to add a JPanel placeholder to the GUI and add the chart to that in user code. Because of the same constraint I can't have a generic parameter on the wrapping class.
public class InteractiveChart<C extends Chart> extends JPanel {
private final C wrappedChart;
public InteractiveChart() {
// Compiler error: at this point C can be any other subclass of Chart
this(new SimpleChart());
}
public InteractiveChart(C chart) { wrappedChart = chart; }
public C getWrappedChart() { return wrappedChart; }
}
How can I solve the dilemma between 1 and 2?
My current best solution is to create a subclass of InteractiveChart called InteractiveSimpleChart that fixates the generic parameter. I hope to find a way to eliminate this subclass, as every time I add a new kind of Chart I'd have to add a new wrapper for interactivity too.
I'm probably not explaining this well, but the type
Ccan only be a single type at once. When you sayC extends Chart, you're restricting what type that C can be, but at the end of the day it can only be one of those types. In other words, any given InteractiveChart might be an InteractiveChart of type Chart or an InteractiveChart of type SimpleChart, but not both at the same time.So as it's written, your second constructor must take that exact type.
C extends Chartdoes not mean "any class that extends Chart". It means "a specific class, which happens to extend Chart". You get the compile error because the constructor requires a class of type C, but you're trying to supply it with a class of type SimpleChart. C may not be a SimpleChart. It may be a Chart or maybe SomeOtherChart for example.TL;DR: in order to require 'any class that extends Chart' in your second constructor, you simply use
Chartinstead ofC. :)Problem solved.
Of course, this brings up a better question, which is do you really need to use generics here? So far you haven't shown anything that requires it.