Wie zu werfen einen Iterator der Klasse einen Iterator, der einer Subklasse?
Versuchte ich warf einen Iterator der Klasse einen iterator, der eine Unterklasse der Klasse sagte. Dies gab mir ein "inconvertible types" Fehler. Warum ist dies nicht möglich, und was ist der eleganteste Weg das zu umgehen? (Oder alternativ, warum ist es eine schlechte Idee, wenn es ist?)
Mithilfe einer for-each-Schleife ist keine Lösung in diesem Fall: ich bin versucht zu implementieren iterator()
und der einfachste Weg, dies zu tun wäre, um die Rückkehr der iterator()
einer meiner Klasse " Felder, aber dass man nicht über den gewünschten Typ. Ich kann es nicht ändern, die Signatur von meinem iterator()
entweder.
public interface SomeoneElsesInterface {
public Iterator<SomeoneElsesInterface> iterator();
}
public abstract class MyAbstractClass implements SomeoneElsesInterface {
final MyAbstractClass[] things;
public MyAbstractClass(SomeoneElsesInterface... things) {
this.things = (MyAbstractClass[]) things;
}
}
public class MyClass extends MyAbstractClass {
public MyClass(MyAbstractClass thing1, MyAbstractClass thing2) {
super(thing1, thing2);
}
public Iterator<SomeoneElsesInterface>() {
return (Iterator<SomeoneElsesInterface>) Arrays.asList(things).iterator();
}
}
Konnte ich, natürlich, ändern Sie einfach die Art von things
. Jedoch bräuchte ich eine Menge von Besetzungen in anderen Orten, in diesem Fall. Ich weiß, dass mein Konstruktor nicht aufgerufen werden, mit Gegenständen, die nicht MyAbstractClass
s, aber ich kann nicht ändern das interface sowieso.
- Was (wenn überhaupt etwas) ist die Beziehung zwischen dem Typ der Klasse und der Art der enthaltenen Feld? Können Sie uns zeigen, einige code?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sieht dies so einfach wie mit explizite Typ-argument Spezifikation:
Das problem ist, dass
Arrays#asList()
ist abzuleiten, dass eine Liste vom TypList<MyAbstractClass>
, die Ausbeute wird ein iterator vom TypIterator<MyAbstractClass>
. DaIterator
's type-parameter ist nicht kovariante, die Sie nicht liefern kann eineIterator<MyAbstractClass>
wo einIterator<SomeoneElsesInterface>
erforderlich ist. Durch erzwingenArrays#asList()
zum erstellen einer Liste von TypList<SomeoneElsesInterface>
, wie oben gezeigt, werden Sie auch wind-up mit der beabsichtigten iterator-Typ kommen zurück von Ihrem AufrufIterable#iterator()
.Autor
SomeoneElsesInterface
gewesen wäre, kinder angeben, die Rückkehr der Typ deriterator()
Methode alsIterator<? extends SomeoneElsesInterface>
.Ich denke, aus Ihrer Frage, die Sie versuchen zu tun, so etwas wie dieses:
Ist das richtig?
Wenn ja, das ist leider unmöglich. Das problem ist, dass
original
können Objekte enthalten, die nichtString
s, so so dass dass cast brechen würden den Generika-Vertrag, d.h.converted
enthalten könnte etwas, das nicht einString
.Ich glaube nicht, dass es einen eleganten workaround für dieses.
Ihnen sagen, die einfachste Möglichkeit zum implementieren von
iterator()
ist, um eine Instanz-Feld iterator, so dass ich vermute, Sie haben so etwas wie dieses:Wenn
someStuff
gewährleistet werden kann, enthält nur Instanzen vonFoo
, dann können Sie erklärensomeStuff
eineCollection<Foo>
eher als eineCollection<Bar>
? Wenn nicht, dann ist es nicht wirklich sinnvoll, nur zurücksomeStuff
's iterator, weil es könnte etwas beinhalten, das nicht einFoo
.Ich denke, Sie müssen denken, über welche Garantien kann man tatsächlich machen. Wenn Sie nicht garantieren können, dass
someStuff
enthält nurFoo
s, dann werden Sie wahrscheinlich haben, um Ihren eigenen Zustand, oder filtern Sie den Inhalt dersomeStuff
auf Nachfrage.EDIT: hast Du aktualisiert, deine Frage mit code. Genial.
So wie es aussieht bist du tatsächlich versuchen, zurück einen iterator über die Oberklasse der Typ. Das macht die Dinge viel einfacher.
In Ihrem speziellen Fall, können Sie wahrscheinlich lösen es mit diesem:
Es generieren werden einige Warnungen, aber das ist OK, weil Sie wissen, dass Sie garantiert haben Art Sicherheit.
original
ist eigentlich einIterator
vonSubclass
, und ich willconverted
eineIterator
einer Oberklasse vonSubclass
. Ich kann daher garantieren, dass original nur Elemente enthält, die (transitiv) von Instanzen der Klasse.Verwenden
for-each
loop stattIterator
.for-each
wurde von Java 1.5Siehe diesen link für weitere details:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
Was, wenn Sie ändern
Arrays.asList(things)
zuArrays.asList((SomeoneElsesInterface[]) things)
? Sobald das array cast in den richtigen Typ der Liste und Iterator Folgen sollten.Beispiel von Java for-each (Ergänzung Kumar Antwort):