2017-07-06 4 views
1

Ich versuche, meine benutzerdefinierte Klasse mit einem Iterator zu verwenden, aber es kann nicht auf die Elemente mit foreach iterieren. Wie kann ich damit umgehen?Warum kann ich foreach nicht für meine Klasse verwenden?

public class FCSOfOtherClass<Double> { 
private int n; 
private Double[] a; 

public FCSOfOtherClass(int cap) { 
    a = (Double[]) new Object[cap]; 
} 

public void push(Double dou) { 
    if (a.length == n) { 
     this.resize(2 * a.length); 
     a[n++] = dou; 
    } else { 
     a[n++] = dou; 
    } 
} 

private void resize(int max) { 
    Double[] newa = (Double[]) new Object[max]; 
    for (int i = 0; i < n; i++) { 
     newa[i] = a[i]; 
     a = newa; 
    } 
} 

public Boolean isEmpty() { 
    return n == 0; 
} 

public Double pop() { 
    Double dou = a[--n]; 
    a[n] = null; 
    if (n > 0 && n == a.length/2) { 
     resize(a.length/2); 
    } 
    return dou; 
} 

public int size() { 
    return n; 
} 

public Iterator<Double> iterator() { 
    return new RAIterator(); 
} 

private class RAIterator implements Iterator<Double> { 
    private int i = n; 

    @Override 
    public boolean hasNext() { 
     return i > 0; 
    } 

    @Override 
    public Double next() { 
     return a[--i]; 
    } 

    @Override 
    public void remove() { 

    } 

    @Override 
    public void forEachRemaining(Consumer<? super Double> action) { 

    } 

Das ist meine Hauptmethode:

public static void main(String[] args) { 
    FCSOfOtherClass<Integer> fcs = new FCSOfOtherClass<>(100); 
    int i = 0; 
    while (!StdIn.isEmpty()) { 
     fcs.push(++i); 
    } 
    for (int j:fcs) { 
     StdOut.print(j); 
    } 
} 

Als ich das laufen, ich einen Fehler mir zu sagen, dass foreach meine Art nicht anwendbar ist.

+11

Eine Klasse muss die Iterable-Schnittstelle implementieren, damit sie in einem for-each-Block verwendet werden kann. –

+2

Nicht verwandt, aber den generischen Typparameter 'Double' nicht nennen. Es ist * sehr * verwirrend, Variablen des Typs 'Double' zu ​​sehen, die nicht' java.lang.Double' sind, sondern alles sein könnten, z. 'Frucht'. [Namenskonvention] (https://stackoverflow.com/documentation/java/2697/oracle-official-code-standard/9031/naming-conventions#t=201707061649005848894) für Typvariablen ist generell ein einzelner Großbuchstabe zu verwenden, am häufigsten 'T'. In Ihrem Fall wäre "E" für "Element" ein anderer geeigneter Name. – Andreas

Antwort

6

Ihre Klasse FCSOfOtherClass implementiert java.lang.Iterable nicht. Die Foreach-Schleife funktioniert nur für Arrays und Instanzen von Iterable.

Sie können diese Adresse Ihre Klasse Iterable implementieren, indem sie:

public class FCSOfOtherClass implements java.lang.Iterable<Double> { 
    ... 
} 

Dies erfordert, dass Sie eine Implementierung für die Interface-Methode iterator() bereitzustellen. Ihr Beispielcode zeigt, dass Sie bereits tun:

public Iterator<Double> iterator() { 
    return new RAIterator(); 
} 

Diese in der Java Language Specification abgedeckt ist, section 14.14.2: The enhanced for statement:

Die Art des Ausdrucks Iterable sein muss oder ein Array-Typ (§10.1), oder ein Kompilierungsfehler tritt auf.

+1

Das Lustige ist, dass er alles * fast * richtig gemacht hat - er hat nur vergessen zu erklären, dass seine Klasse die 'Iterable' Schnittstelle implementiert hat;) –

Verwandte Themen