Ich bin also ziemlich neu in der Programmierung in der realen Welt (außerhalb von akademischen Projekten) und habe viele Beiträge gesehen, die besagen, dass die Verwendung instanceof
eine schlechte Sache ist, um festzustellen, welche Klasse ein bestimmtes Objekt ist.
Meine Situation ist, dass ich drei Klassen habe, eine Basisproduktklasse, eine, die sich darüber erstreckt, und eine andere, die sich darüber erstreckt. Diese sind alle in derselben Tabelle in einer Datenbank gespeichert, und ich habe Code, der die Methoden für jede verwenden muss, um Daten von ihnen abzurufen.
Was ist die beste Vorgehensweise, um diese Vorgehensweise zu umgehen? Ich habe einige Dinge über Polymorphismus gelesen, kann aber keine Beispiele finden, die das Problem beheben, das ich habe. Sie alle überschreiben normalerweise eine Methode, die für mich nicht funktioniert, da ich verschiedene Dinge aus den verschiedenen Objekten ziehen muss.
Gibt es einen besseren Weg, dies zu tun, oder bin ich bei der Verwendung instanceof
oder einer Art Reflexion festgefahren , um die für die Objekte spezifischen Felder zu erhalten?
quelle
instanceof
falsch ist; Der Versuch, die Klasse eines Objekts zu finden, ist normalerweise das Problem. Nicht immer falsch, aber wahrscheinlich in Ihrem Fall. Wenn Sie uns mitteilen, was Sie erreichen möchten, können wir möglicherweise eine Lösung mit Polymorphismus vorschlagen.getSpecifics()
, die auf jeder Methode unterschiedlich implementiert ist und bei der die für die Klasse spezifischen Daten zurückgegeben werden?Antworten:
Der Grund
instanceof
ist entmutigt, dass es nicht OOP ist.Es sollte keinen Grund für den Aufrufer / Benutzer eines Objekts geben, zu wissen, um welche konkrete Klasse es sich handelt, ab welchem Typ die Variable deklariert ist, als die es deklariert ist.
Wenn Sie in Unterklassen ein anderes Verhalten benötigen, fügen Sie eine Methode hinzu und implementieren Sie sie anders.
quelle
getSpecifics()
(oder ähnliches) für jede Klasse, die die Details für jede Klasse zurückgibt. Ist das der beste Ansatz?List
. Ich gebe es an ein Objekt weiter, das eines nimmtIterable
. Jetzt übergibt dieses zweite Objekt es an ein drittes Objekt, das entweder einList
zur Optimierung benötigt oder ein,Iterable
aber viel langsamer ist. Der zweite sollte nicht wissen, dass es eine Liste ist, aber der dritte würde es sehr gerne wissen. Sollte das dritte Objekt nicht beispielsweise prüfen, ob es die Optimierung anwenden kann? Siehe zum Beispiel GuaveFluentIterable
, die genau das tut.instanceof
.instanceof
ist nicht unbedingt eine schlechte Sache, aber es ist etwas, das man sich ansehen sollte.Ein Beispiel dafür, wo es richtig funktioniert, ist ein Ort, an dem man eine Sammlung des Basistyps erhält und nur die eines Subtyps haben möchte. Wenn Sie die Netzwerkadressen
NetworkInterface.getNetworkInterfaces()
von abrufen, werden NetworkInterface-Objekte zurückgegeben, die eine Sammlung von InetAddress-Objekten enthalten, von denen einige Inet4Address und andere Inet6Address sind. Wenn die Auflistung nach Inet4Address-Objekten gefiltert werden soll, muss instanceof verwendet werden.In der Situation, die im ursprünglichen Beitrag beschrieben wird, gibt es eine Basisklasse, die diese Basisklasse erweitert, und etwas, das die erweiterte Klasse erweitert. Dies ist zwar nicht vollständig informativ, scheint jedoch die Grundlage für ein weniger als ideales Design zu haben.
Wenn Sie eine Basisklasse zurückgeben, es sei denn, es gibt einen guten Grund dafür, dass sie so entworfen wurde (Abwärtskompatibilität zwischen Spezifikationen einer früheren Version), sollten Sie nicht versuchen, einen Blick auf die zugrunde liegenden Typen zu werfen. Wenn Sie ein Set zurückerhalten, wissen Sie, dass Sie ein Set erhalten. Es ermöglicht dem Entwickler, später seine Meinung zu ändern, um einen spezifischeren Typ (SortedSet) zurückzugeben oder den zugrunde liegenden Typ (HashSet in TreeSet) zu ändern, ohne etwas zu beschädigen.
Überdenken Sie Ihr Design, wie die Objekte strukturiert und übergeordnet sind, um festzustellen, ob ein besseres Klassenmodell erstellt werden kann, für das keine Unterscheidung der Typen erforderlich ist.
quelle
isOfType(SomeEnum.IPv4)
Methode durch die Schnittstelle eine bessere Möglichkeit ist, nach solchen Eigenschaften zu filtern, als den Betontyp über zu überprüfeninstanceof
. Was ist, wenn Sie Ihre IPv4-Implementierungsklasse später aufteilen möchten? Nicht dass das immer besser ist, aber es ist eine Überlegung.(o instanceof Serializable) || (o instanceof Externalizable)
. instanceof ist besser als die AlternativeSie können die Methode getClass () verwenden.
Bist du sicher, dass du drei verschiedene Klassen brauchst? Vielleicht dient eine Klasse mit einem Schalter im Inneren besser?
quelle
getClass
undinstanceof
Nachteile teilen. Polymorphismus ist besser als beides, wenn er passt, und ich sehe nicht, dass er nicht zum Anwendungsfall von OP passt.getClass
teile ich nicht immer noch das gleiche Problem wie mitinstanceof
? Ich muss noch herausfinden, welche ich habe, und dann eine Reihe von Funktionen aufrufen. Idealerweise möchte ich eine Methode, die die für diese Klasse spezifischen Daten zurückgibt, ohne dass sie in dieses Objekt umgewandelt werden müssen.getClass
ist ein besserer Weg, es zu tun, es hat nichts damit zu tun, die meisten Antworten aufzunehmen ;-)Wenn ich die Art von etwas wissen möchte, bedeutet dies normalerweise, dass ich meine Objektstruktur falsch implementiert habe. In den meisten Fällen kommt es darauf an, LSP zu verletzen .
Es gibt jedoch Zeiten, in denen ich mir wünschte, ich hätte eine Möglichkeit, dynamisch zu versenden, eine Tonne Kesselplattencode zu speichern und meine Objektstruktur zukunftssicher zu machen. C # liefert das dynamische Schlüsselwort in den neueren Raten des Frameworks, aber meines Wissens hat Java noch nichts Ähnliches.
Allerdings ist instanceof im Allgemeinen besser als das Vergleichen von Klassen, da es die Vererbung ordnungsgemäß unterstützt. Sie können auch Methoden wie isAssignableFrom und andere aus der Reflexions-API verwenden. Wenn Sie so etwas wie einen dynamischen Versand implementieren möchten, kann dies über die Reflection-API erfolgen. Beachten Sie jedoch, dass dies langsam ist. Verwenden Sie diese Option mit Vorsicht. Idealerweise sollten Sie die Objektstruktur und das Design Ihrer App korrigieren, wenn Sie können.
Hoffe das hilft
quelle