【问题标题】:java composite design pattern with generics带有泛型的java复合设计模式
【发布时间】:2011-10-10 10:48:11
【问题描述】:

我有两个通用接口IComparable<T>,带有方法public boolean gt(T t)ICombinable<T>,带有方法public T combine(T t),以及第三个接口IPreferenceValue<T>,它扩展了这两个接口,即IPreferenceValue<T> extends IComparable<T>, ICombinable<T>,这样T 类型的首选项值可以与其他T 进行比较和组合。我有两个 IPreferenceValue 的具体实现,一个是单值实现:IntegerValue implements IPreferenceValue<IntegerValue>,另一个是偏好值列表:PreferenceVector<S extends IPreferenceValue<S>> implements IPreferenceValue<PreferenceVector<S>>

在其他地方,我有一个算法可以在 IPreferenceValues 上执行各种操作,我想通过接口以相同的方式处理单值和列表值 Preference 值,例如复合设计模式。我还希望有某种 Factory 可以根据某些参数创建 IPreferenceValues,即创建一个单值对象,或创建一个列表值对象。但是,当我创建这些 PreferenceValues 时,我并不关心 Parameter 类型,我只想创建 IPreferenceValue 类型的对象,工厂将返回具体实现 - 并且只需使用接口与对象交互。

但是,我在让它工作时遇到了一些困难。首先,如果我使用原始类型 IPreferenceValue 声明我的值,我会收到这些警告 - “IPreferenceValue is a raw type. References to generic type IPreferenceValue<T> should be parameterized”。这些警告可以避免吗?在其他地方,我将它们声明为IPreferenceValue<?>,我收到以下错误:The method gt(capture#6-of ?) in the type IComparable<capture#6-of ?> is not applicable for the arguments (IPreferenceLevel<capture#7-of ?>)。非常感谢任何建议或指示...

编辑: 这是我得到第二个错误的地方 (The method gt(capture#12-of ?) in the type IComparable<capture#12-of ?> is not applicable for the arguments (IPreferenceLevel<capture#13-of ?>))

private IPreferenceLevel<?> calculateMinValue()
{
    IPreferenceLevel<?> min = null;
    for (IPreferenceLevel<?> value : tupleToValueMap.values())
    {
        if ((min == null) || (min.gt(value).equals(Comparison.TRUE)))
        {
            min = value;
        }
    }
    return min;
}

但是,即使我为此方法输入了一个类型,即,如果我重写如下 -

private <X> IPreferenceLevel<X> calculateMinValue()
{
    IPreferenceLevel<X> min = null; ...

这仍然无法编译 - The method gt(X) in the type IComparable&lt;X&gt; is not applicable for the arguments (IPreferenceLevel&lt;capture#10-of ?&gt;)

【问题讨论】:

  • 注意:除了像 Eclipse 这样的少数项目,ISomething 命名模式在 Java 中是不常见的。尝试使用真实的单词(或至少是复合单词)
  • 你的IntegerValue是一个具体的类吗?那么它如何扩展一个接口IPreferencevalue
  • @Bhaskar - 你说得对,我的意思是输入“实现”
  • 如果您在映射中存储任意类型的值,我认为这可能是编译器中的真正错误。我已根据您的编辑更新了我的答案。

标签: java generics


【解决方案1】:

您没有就具体错误案例提供足够的背景信息,让我无法明确指出问题所在。所以我必须给出更一般的指示。

首先,原始类型警告是正确的。可以说原始类型的存在只是为了向后兼容,你永远不应该在新代码中使用它们。 IPreferenceValue 始终具有泛型类型 - 如果您不知道它是什么并且不在乎,请将其作为 IPreferenceValue&lt;?&gt; 返回,就像您已经完成的那样。这很好,并且基本上表明您不知道/不关心该参数。 (当然,如果你知道它可能是什么,那么一定要提供一个更具体的参数。)

第二个错误似乎是合法的 - 您需要传入 T,但您正在尝试传入 IPreferenceValue&lt;T&gt;

而且,一旦你解决了这个问题,你仍然会遇到问题。潜在错误以完全不同的方式发生,并且在泛型中并不少见。你有一个对IPreferenceValue&lt;?&gt; 的引用,并且你正试图调用它的gt 方法,该方法被定义为采用T。但是您刚刚说过您完全不知道该对象的 T 是什么(这就是您使用通配符的原因) - 如果您不知道通用参数是什么,您如何传入 有什么 并且知道它是正确的类型吗?

具体来说,您正在尝试将tupleToValueMap 的内容相互比较。为了合法地做到这一点,它们的泛型类型参数必须相同 - 你如何比较 IPreferenceLevel&lt;IntegerValue&gt;IPreferenceLevel&lt;PreferenceVector&lt;S&gt;&gt;

因此,您应该更具体地声明tupleToValueMap 的类型,为偏好级别而不是? 提供一个具体的通用参数。如果事实证明您不能这样做,因为您在其中放置了多种类型的偏好级别 - 那么编译器错误是正确的,您无法安全地将它们相互比较。

【讨论】:

    猜你喜欢
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    • 2018-01-24
    • 1970-01-01
    相关资源
    最近更新 更多