【问题标题】:Interface casting for `Iterable``Iterable` 的接口转换
【发布时间】:2013-12-19 18:54:23
【问题描述】:

如果我有一个名为Cue 的类实现Tickable。后来,我有一个像这样的可观察列表:ObservableList<Cue> oListoList 实现 Iterable<Cue>(这就是 ObservableList 的声明方式)。

我有一个接受Iterable<Tickable> 的函数。如何让它接受 ObservableList<Cue> Cue 是 Tickable 而 ObservableList 是 Iterable。出于某种原因,我不能在他们之间进行种姓或自动向上转换。有没有办法做到这一点?

【问题讨论】:

  • 你会这么好心并分享一些代码吗?

标签: java generics interface polymorphism javafx


【解决方案1】:

您不能从Iterable<Cue> 转换为Iterable<Tickable>,因为即使CueTickableIterable<Cue> 也不是Iterable<Tickable>,因为Java 的泛型是不变的。

要让方法接受ObservableList<Cue>,方法参数类型为Iterable<Cue> 或使用有界通配符——Iterable<? extends Tickable>

【讨论】:

    【解决方案2】:

    正如 rgettman 所说,您应该将函数参数类型更改为Iterable<? extends Tickable>

    这是因为Iterable 是一个生产者(它只从一个方法返回T)。因此,根据 PECS(生产者extends,消费者super)规则,应始终使用extends 通配符对其进行参数化。在正常使用中,没有理由使用Iterable<Something> 代替Iterable<? extends Something>。 (唯一需要Iterable<Something> 的情况是,如果您打算将其转换回其具体类型或类似的奇怪类型。)

    【讨论】:

      【解决方案3】:

      可以通过删除通用类型信息来做到这一点:

      public static void main(String[] args) {
          ObservableList<Cue> oList = new ObservableList<Cue>();
          naughtyCall(oList);
      }
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      static void naughtyCall(ObservableList oList) {
          doSomething(oList);
      }
      
      static void doSomething(Iterable<Tickable> iterable) {
          // TODO
      }
      

      不过,我不建议这样做!请参阅 rgettman 的回复以了解您应该做什么。


      更新:对于有兴趣玩这个的人,这里是我用来重现 OP 情况的其余代码:

      class Cue implements Tickable {
      
      }
      
      interface Tickable {
      
      }
      
      static class ObservableList<T> implements Iterable<T> {
      
          @Override
          public Iterator<T> iterator() {
              return null;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-08-28
        • 1970-01-01
        • 1970-01-01
        • 2010-11-07
        • 2013-03-03
        • 2010-10-10
        • 2011-02-25
        • 2010-11-06
        • 2014-09-19
        相关资源
        最近更新 更多