【发布时间】:2011-11-07 21:28:17
【问题描述】:
这是一个令人讨厌的问题,可能是设计很糟糕。
编写一组简单的图表组件(饼图、条形图和折线图),并且对一些泛型的东西感到窒息。在此之前,我确信有很多 Java API 可以完全按照我在这里尝试做的事情(图表/报告/等),但是我对此感兴趣,因为这是一个通用的泛型问题;它涉及图表和报告组件的事实是微不足道的。
每个图表都继承自一个通用抽象基类Chart:
public abstract class Chart<T extends ChartComponent>
{
private List<T> components;
// ...rest of the Chart class
}
我们之所以有T extends ChartComponent 是因为每个图表子类都将由 1+ 个所谓的图表组件(条形、线条、饼形楔形等)组成:
public abstract class ChartComponent
{
private Color color;
// .. rest of ChartComponent class
}
public class PieWedge extends ChartComponent
{
double wedgeValue;
// ... rest of PieWedge class
}
把这个设计放在一起:
public class PieChart extends Chart<PieWedge>
{
// ... thus its list of ChartComponents is actually a List<PieWedge>
}
这样,PieChart 不是泛型的(也不应该是泛型的)并且始终是Chart<PieWedge> 类型。
我之前对条形图和折线图有相同的设置,分别定义为 BarChart extends Chart<BarGroup> 和 LineChart extends Chart<Line>(因为条形图由 1+ 组条组成,而折线图由 1+ 条线组成) .
现在我想进一步抽象条形图和折线图。这两个图表实际上都是针对具有 x 轴和 y 轴的 (x,y) 笛卡尔图绘制的;这与不针对任何此类轴绘制的饼图相反。
理想情况下,我想创建一个名为CartesianChart 的新抽象类,它扩展Chart,然后让BarChart 和LineChart 都扩展CartesianChart。这个新的CartesianChart 将引入新的属性(xAxisLabel、gridTurnedOn 等),这些属性在逻辑上适用于条形图/折线图,但不适用于饼图。
此外,为了限制CartesianChart,使其只能具有chartComponents 类型为BarGroup 或Line(而不是PieWedge),我想创建一个新的图表组件类型,如CartesianComponent extends ChartComponent ,然后让BarGroup/Line 扩展它。这样做会阻止这样的代码编译:
LineChart lineChart = new LineChart();
lineChart.addLine(new PieWedge());
由于Line 扩展了CartesianComponent,但PieWedge 仅扩展了ChartComponent。因此,在解决我的问题之前,我们有以下继承层次结构:
Chart
CartesianChart
BarChart
LineChart
PieChart
ChartComponent
CartesianComponent
BarGroup
Line
PieWedge
PieChart extends Chart<PieWedge>
CartesianChart extends Chart<CartesianComponent>
BarGroup extends CartesianComponent
Line extends CartesianComponent
BarChart extends CartesianChart<BarGroup>
LineChart extends CartesianChart<Line>
此设置的问题在于,在BarChart 和LineChart 上都会出现编译器错误,抱怨CartesianChart 不是通用的。 这完全有道理,但我不确定我能做些什么来解决它!
如果我尝试重新定义CartesianChart:
public abstract class CartesianChart<T extends CartesianComponent> extends Chart<CartesianComponent>
{
// ...
}
我的条形图/折线图代码都出现“类型不匹配”编译器错误。在每个错误实例中,它都声明它需要 List<CartesianComponent> 类型的参数,但发现 List<BarGroup> 或 List<Line> 并且它们不是合适的替代品。
希望这是CartesianChart 和/或CartesianComponent 的类定义中某处的快速修复。否则我可能不得不重新设计整个图表库。无论哪种方式,我都对任何和所有建议都感兴趣,除了诸如“嘿,你为什么不试试 JFreeCharts 或 ...”之类的建议。同样,我对这里的解决方案很感兴趣,因为它与解决广泛的类似泛型问题有关;这涉及报告/图表的事实是微不足道的。
提前感谢您的任何帮助!
【问题讨论】:
-
你想通过使
Chart通用来实现什么?换句话说,为什么不直接定义class Chart { private List<ChartComponent> components; }? -
public abstract class CartesianChart<T extends CartesianComponent> extends Chart<T>? -
感谢您的建议。我会在这里尝试你的两个建议。请参阅我在@nicholas.hauschild 下方的评论,我担心扩展 Chart
不会阻止子类在 T 不扩展 ChartComponent 的地方创建 Chart。