【问题标题】:Multiple inheritance generics in reference type引用类型中的多重继承泛型
【发布时间】:2017-12-19 18:02:33
【问题描述】:

给定:一个具有泛型 T 类型的类,它扩展并实现了一个接口

class RescheduableRunnableIntent<T extends Intent & Timmed> implements Runnable{
    IntentManager intentManager;
    T intent;
}

如何为 ArrayList 或 Hashmap 指定相同的条件?以下行产生语法错误

private HashSet<? extends Intent & Timmed> set;

【问题讨论】:

  • 用例到底是什么?你能把通用规范提升到类级别吗?
  • 一种解决方法是创建一个实现IntentTimmed 的类并在泛型中扩展该类
  • 我认为是T extends X &amp; Y1,而不是?。您需要在那里实际使用类型变量。但大多数情况下,您会使用 T 来表示已声明的某些类型。
  • 我尝试使用 T 代替我能想到的任何排列。正如@Oswald 建议的那样,在两者之间创建一个抽象类可以解决这个问题。我很惊讶没有办法以另一种方式处理它。用例是一个事件系统,它应该以重复的方式执行任务(意图)。延迟不一定是固定的,但可能取决于一周中的一天中的其他外部条件。因此,此类包装了 2 个可运行对象,它们将一个接一个地执行(任务和重新调度操作)到另一个可运行对象中。
  • answer。对于为什么没有办法以另一种方式处理它,这是非常深刻的解释。

标签: java generics


【解决方案1】:

我不喜欢使用类型通配符,因为它们限制太多。比如说,检查这个代码示例:

List<? extends Number> listExtendsNumber = new ArrayList<>(Arrays.asList(1, 2, 3));
Number num = new Integer(1);
listExtendsNumber.add(num); // compile error - you can't add stuff
listExtendsNumber.add(1);   // compile error - you can't add stuff

有时你真的想变得如此严格。但是,我发现使用绑定通配符类型的人通常想要别的东西。

您需要确定是否要接受扩展IntentTimmed任何 类型,还是只接受一种特定类型?

据我所知,您有以下选择:

1。 Set 周围的包装器

您可以指定处理一种特定类型的包装器:

public class TimmedIntentSet<T extends Timmed & Intent> implements Set<T> {


    private Set<T> set = new HashSet<>();

    // consider defining constructors other than the default

    @Override
    public int size() {
        return set.size();
    }

    @Override
    public boolean isEmpty() {
        return set.isEmpty();
    }
    // ... more delegator methods
}

这可以非常灵活。例如,考虑以下类型:

public interface Timmed {}
public interface Intent {}
public interface TimmedIntent extends Timmed, Intent {}
public class TimmedIntentClass implements TimmedIntent {}
public class TimmedAndIntent1 implements Timmed, Intent {}
public class TimmedAndIntent2 implements Timmed, Intent {}

如果您对某些类型检查警告感到满意,那么您几乎可以用这个TimmedIntentSet 做任何事情:

    TimmedIntentSet tis = new TimmedIntentSet<>(); // warning
    tis.add(new TimmedAndIntent1());  // warning
    tis.add(new TimmedAndIntent2());  // warning
    tis.add(new TimmedIntentClass()); // warning
    tis.add(2);                       // compile error

但是,如果您不想 @Suppress 您的警告,那么您会看到很多限制:

    TimmedIntentSet<TimmedIntentClass> tis = new TimmedIntentSet<>();
    tis.add(new TimmedAndIntent1());  // compile error
    tis.add(new TimmedAndIntent2());  // compile error
    tis.add(new TimmedIntentClass()); // cool
    tis.add(2);                       // compile error

2。将 Set 添加到使用它的类中

您可以在上面刚刚指定的类中添加一个 Set。这接受一种特定类型:

class RescheduableRunnableIntent<T extends Intent & Timmed> implements Runnable{
    IntentManager intentManager;
    T intent;
    Set<T> intentMap;
}

您可以定义TimmedIntent 的新类型,但有其他类型的限制。使用与上述相同的类型,您不能只将任何 TimmedIntent -s 添加到您的集合中:

Set<TimmedIntent> set = new HashSet<>();
set.add(new TimmedAndIntent1());  // compile error
set.add(new TimmedAndIntent2());  // compile error
set.add(new TimmedIntentClass()); // only this is fine

总结:

这一切都归结为你想做什么?几乎一切皆有可能,但每种选择都需要权衡取舍。

【讨论】:

    猜你喜欢
    • 2011-08-19
    • 2011-08-17
    • 2018-09-27
    • 2015-09-15
    • 2018-08-01
    • 1970-01-01
    • 2022-10-07
    • 2020-01-05
    相关资源
    最近更新 更多