【问题标题】:Empty constructor in parametrized class参数化类中的空构造函数
【发布时间】:2018-08-01 15:46:24
【问题描述】:

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

1) 因为Chart 的不同子类可以具有不同的“额外”功能,所以我希望在包装类中有一个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之间的困境?

我目前最好的解决方案是创建一个名为InteractiveSimpleChart 的InteractiveChart 的子类,它固定泛型参数。我希望找到一种方法来消除这个子类,因为每次我添加一种新的图表时,我都必须添加一个新的交互包装器。

【问题讨论】:

  • 什么是“使用”派对?
  • 如果需要无 arg 构造函数,那为什么还要有 1 arg 构造函数呢?泛型的目的是什么?
  • @zhh,他要实例化new C()。但是他不能这样做,因为你怎么知道 C 有一个无参数的构造函数?
  • 你需要提供更多关于你想要做什么的信息,因为它很不清楚。但是,据我了解,您应该创建 InteractiveSimpleChart、InteractiveComplexChart、InteractiveWhateverOtherChartsYouHaveChart 并实例化 它们,而不是 Interactive 等。
  • 我想这应该可以通过一点反射魔法来实现,但我似乎无法让 type-munging 玩得很好。

标签: java generics gui-builder


【解决方案1】:

我可能没有很好地解释这一点,但类型 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) { .. }

问题解决了。

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

【讨论】:

  • 这实际上并不能解决问题;他们必须有一个无参数的构造函数来满足 GUI builder 的要求。
  • @ChiefTwoPencils 无参数构造函数还在。
  • 您的第一个建议——保持InteractiveChart&lt;C&gt; 通用,但给它一个构造函数,该构造函数采用任何Chart 而不是专门的C——恕我直言,没有任何意义。但是您的第二个建议 - 将 InteractiveChart&lt;C&gt; 更改为 InteractiveChart (非通用) - 可能是一个不错的建议,具体取决于 OP 的需求。
  • 泛型的原因是用于检索包装图表的getter(我忘了把它放在问题的例子中)
  • @MarkJeronimus 我想我明白你在做什么,你最初的感觉是对的——它不能用泛型来完成。完成您需要的最不可怕的方法是始终将对象作为图表返回并根据需要进行转换(或仅依赖多态性)。
【解决方案2】:

所以,据我了解,您的要求是:

  • 您有某种 GUI 构建器框架,由于某种不幸的原因,它只获取类名或 Class&lt;?&gt; 实例或诸如此类的东西,并使用无参数构造函数。对于此框架,您需要InteractiveChart&lt;SimpleChart&gt;,图表为new SimpleChart()。
  • 您还有其他代码可以从更大的灵活性中受益:您希望为除了 SimpleChart 之外的不同图表类型创建 InteractiveChart&lt;C&gt; 实例。

我有这个权利吗?

那么,问题在于 Java 不允许您定义仅适用于 InteractiveChart&lt;SimpleChart&gt; 的构造函数——InteractiveChart 的任何构造函数都必须适用于任意 C——所以你'正在尝试为任意 InteractiveChart&lt;C&gt; 定义一个构造函数,它只是 假设 C 是 SimpleChart,这(我希望你会同意)不是一个很好的假设,并且不是 Java 支持的假设。

一个简单的解决方法是为您的 GUI 构建器框架创建一个 InteractiveChart&lt;SimpleChart&gt; 的子类来实例化:

public class SimpleInteractiveChart extends InteractiveChart<SimpleChart> {
    public SimpleInteractiveChart() {
        super(new SimpleChart());
    }
}

然后您的 GUI 构建器框架可以使用 new SimpleInteractiveChart(),而您的其他代码仍然可以使用带有任何类型参数的 InteractiveChart&lt;C&gt;。

【讨论】:

    猜你喜欢
    • 2017-04-01
    • 1970-01-01
    • 2017-10-02
    • 2022-09-23
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 2016-03-05
    相关资源
    最近更新 更多