参数化类中的空构造函数

时间:2018-08-01 15:46:25

标签: java generics gui-builder

我有一个类InteractiveChart,该类包装了一个Chart(接口),并通过将用户交互映射到Chart上的setter调用来为其添加交互性。

1)因为Chart的不同子类可以具有不同的'extra'功能,所以我希望包装类中有一个getter来返回包装的Chart(不需要进行未经检查的强制转换!) 。我唯一知道的方法是在包装类上有一个通用参数。

2)此包装类也打算在NetBeans的GUI Builder中使用,它具有需要一个空构造函数的约束。但是,泛型参数的运行时类型由实例化它的代码确定,我无法控制NetBeans实例化它的方式。在这种情况下,我希望它包装一个SimpleChart,如果用户想包装其他东西,他们将不得不在GUI中添加一个JPanel占位符,并在用户代码中将其添加到图表中。由于相同的约束,我在包装类上没有通用参数。

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; }
}

如何解决1到2之间的难题?

我目前的最佳解决方案是创建一个称为InteractiveChart的{​​{1}}子类,该子类可修复通用参数。我希望找到一种消除该子类的方法,因为每次添加一种新的Chart时,我也必须添加一个新的包装来实现交互性。

2 个答案:

答案 0 :(得分:0)

我可能无法很好地解释这一点,但是类型C一次只能是单个类型。当您说C extends Chart时,您在限制C可以是哪种类型,但是到最后,它只能是这些类型之一。换句话说,任何给定的InteractiveChart都可以是Chart类型的InteractiveChart或SimpleChart类型的InteractiveChart,但不能同时使用。

如此,您的第二个构造函数必须采用该确切类型。 C extends Chart 不是的意思是“任何扩展Chart的类”。它的意思是“特定类别,恰好扩展了Chart”。因为构造函数需要C类型的类,所以会出现编译错误,但是您正在尝试为其提供SimpleChart类型的类。 C可能不是SimpleChart。例如,它可能是一个图表或SomeOtherChart。

TL; DR:为了在第二个构造函数中要求“扩展Chart的任何类”,您只需使用Chart而不是C。 :)

public InteractiveChart(Chart chart) { .. }

问题解决了。

当然,这提出了一个更好的问题,您真的需要在这里使用泛型吗?到目前为止,您还没有显示任何需要它的东西。

答案 1 :(得分:0)

因此,据我了解,您的要求是:

  • 您有某种GUI生成器框架,由于某些不幸的原因,它仅获得类名或Class<?>实例或诸如此类,并使用no-arg构造函数。对于此框架,您希望InteractiveChart<SimpleChart>的图表为new SimpleChart()
  • 您还具有其他可从更大灵活性中受益的代码:除了InteractiveChart<C>之外,您还想为不同的图表类型创建SimpleChart实例。

我有那个权利吗?

那么,问题是Java不允许您定义仅用于InteractiveChart<SimpleChart>的构造函数-InteractiveChart的任何构造函数都必须应用于任意 {{ 1}} —因此,您正在尝试为任意C定义一个构造函数,而这些构造函数只是假定 InteractiveChart<C>C,(希望您能同意)在这里不是一个很好的假设,也不是Java参与其中的假设。

一个简单的解决方法是为您的GUI生成器框架创建SimpleChart的子类以实例化:

InteractiveChart<SimpleChart>

然后,您的GUI生成器框架可以使用public class SimpleInteractiveChart extends InteractiveChart<SimpleChart> { public SimpleInteractiveChart() { super(new SimpleChart()); } } ,并且您的其他代码仍然可以使用new SimpleInteractiveChart()及其所需的任何类型参数。