迭代器在实现它的类外部预期一个对象的实例。

huangapple go评论69阅读模式
英文:

Iterator expects instance of Object outside of the class which implements it

问题

Alpha.java

class Alpha<E extends Bravo> implements Iterable<Bravo> {
    Bravo head;

    public Alpha(Bravo head) {
       this.head = head;
    }

    public void example() {
       for(Bravo b: this) {
          // This works, it's successfully recognized as an instance of Bravo.
       }
    }

    @Override
    public Iterator<Bravo> iterator() {
        return new BravoIterator(this.head);
    }

    private class BravoIterator implements Iterator<Bravo> {
        private Bravo currentBravo;

        public BravoIterator(Bravo head) {
            this.currentBravo = head;
        }

        @Override
        public boolean hasNext() {
            return this.currentBravo != null;
        }

        @Override
        public Bravo next() {
            Bravo data = this.currentBravo;
            this.currentBravo = this.currentBravo.getNextBravo();
            return data;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }
}

AlphaTest.java

{...}

@BeforeEach
private void setup() {
    // Assume this is a doubly linked list
    Bravo bravo = new Bravo(...);
    
    instanceOfAlpha = new Alpha(bravo);
}

public T1_checkImplementationOfIterableInterface() {
    for(Bravo b: instanceOfAlpha) {  
        // This does not work, it expects an instance of Object.
    }
}

{...}
英文:

couldn't help but feel the title is kinda vague, sorry about that. I couldn't describe it better.

I'll get a little more into detail; I'm trying to figure out how to get an iterator working the way I want it to outside of the class it's implemented in. I couldn't manage to find any information on my problem. This is part of an assignment for University, AlphaTest.java should be left as is.

I have a class, Alpha, which holds a class which follows the doubly linked list principle, Bravo. Bravo holds the link to the previous and next instance in the list.

I want to be able to iterate through the linked list with an iterator implemented in the Alpha class so that I can easily go through each instance using a for loop like this:
for(Bravo b: alphaInstance) {...}.

I got this to work as intended within the Alpha class itself, but once I try the same outside of the Alpha class, in AlphaTest for example, it doesn't work as intended. Once I try that I'm hit with the following error:

Error:(220, 23) java: incompatible types: java.lang.Object cannot be converted to models.Bravo

It wants me to instantiate the instance as an Object like so:

for(Object o: alphaInstance) {...}

I could of course cast the object to Bravo. But that's not part of the assignment.

See code below to see what's going wrong. The problem can be found in AlphaTest.java.

Alpha.java

class Alpha&lt;E extends Bravo&gt; implements Iterable&lt;Bravo&gt; {
    Bravo head;

    public Alpha(Bravo head) {
       this.head = head;
    }

    public void example() {
       for(Bravo b: this) {
          // This works, it&#39;s succesfully recognized as an instance of Bravo.
       }
    }

    @Override
    public Iterator&lt;Bravo&gt; iterator() {
    return new BravoIterator(this.head);
    }

    private class BravoIterator implements Iterator&lt;Bravo&gt; {
       private Bravo currentBravo;

       public BravoIterator(Bravo head) {
          this.currentBravo = head;
       }

        @Override
        public boolean hasNext() {
            return this.currentBravo != null;
        }

        @Override
        public Wagon next() {
            Bravo data = this.currentBravo;
            this.currentBravo = this.currentBravo.getNextBravo();
            return data;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

    }
}

AlphaTest.java

{...}

    @BeforeEach
    private void setup() {
        // Assume this is a doubly linked list
        Bravo bravo = new Bravo(...);
        

        instanceOfAlpha = new Alpha(bravo);
    }

    public T1_checkImplementationOfIterableInterface() {
       for(Bravo b: instanceOfAlpha) {  // &lt;---------------------------------------------[This is the problem]
          // This does not work, it expects an instance of Object.
       }
    }

{...}

答案1

得分: 1

你误解了错误。

问题在于 instanceOfAlpha 是一个表达式,其类型最终为 Alpha - 你省略了关于此变量的定义,但显而易见,因为你使用了原始类型创建了此变量的值。Alpha 将是一个所谓的__原始类型__ - 这是一种具有类型参数但参数缺失的类型。

问题是,原始类型有点奇怪:一旦你使用了原始类型,关于它的一切都是原始的,即使那些并未使用你未指定的泛型的部分也是如此。因此,原始 Alpha 表达式的 iterator() 方法返回一个原始 Iterator(你可能认为它会返回一个 Iterator<Bravo>,但实际不是这样)。因此,对其进行迭代会返回基本对象。因此,你的 for 循环是有问题的;for (Object b : instanceOfAlpha){} 可以编译通过;for (Bravo b : instanceOfAlpha){} 则不能。

修复方法通常是,当编译器在你面前抛出警告时,你不应该只是像 ¯\(ツ)/¯ 这样去理解,即我不知道那些警告是什么意思,所以我会像三只猴子一样,只希望我不理解的东西希望是完全无关紧要的。

实际情况并非如此。真正的修复方法是:修复你的泛型,以便你不会收到这些警告。

你没有粘贴足够的代码,无法准确告诉你在这里需要做什么;可能需要将 instanceOfAlpha 声明为 Alpha<?>。更一般地说,你首次粘贴的 Alpha 类看起来你对泛型的工作原理并不是很理解;在大多数提到 Bravo 的地方,应该使用 E 来代替。泛型有点复杂;也许你想完全放弃它。完全去掉 &lt;E extends Bravo> 部分,然后其余部分基本保持原样,也可以修复问题。

英文:

You've mischaracterized the error.

What's happening is that instanceOfAlpha is an expression whose type ends up being Alpha - you've elided your definition of this variable, but it seems obvious enough, as you're creating the value for this variable with a raw type as well. Alpha would be a so-called raw type - a type that has type parameters, but where the parameters are missing.

The thing is, raw types are a tad odd: Once you go raw, everything about it is raw, even things that aren't using any of the generics you failed to specify. Thus, the iterator() method of your raw Alpha expression returns a raw Iterator (you'd think it returns an Iterator&lt;Bravo&gt;, but it does not). And therefore, iterating over it returns basic Objects. And therefore, your for loop is broken; for (Object b : instanceOfAlpha){} would compile; for (Bravo b : instanceOfAlpha){} won't.

The fix is generally that when the compiler throws warnings in your face that you shouldn't just go ¯_(ツ)_/¯ I don't know what those mean so I'll just be like the 3 monkeys and just wish that whatever I don't understand is hopefully utterly irrelevant.

It's not. The real fix is: Fix your generics so you don't get these warnings.

You haven't pasted enough code to tell you exactly what you need to do here; probably make instanceOfAlpha be declared as a Alpha&lt;?&gt;. More generally, your first paste (of your Alpha class) looks like you just don't get how generics works; most of the places that mention Bravo in that should have been using E instead. generics is a little tricky; perhaps you want to just opt out altogether. Get rid of the &lt;E extends Bravo&gt; part entirely, and then leave the rest pretty much as is, that would also fix things.

huangapple
  • 本文由 发表于 2020年9月21日 21:49:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/63993681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定