Welche Methoden und Schnittstellen implementieren Sie immer in Ihren Klassen?
Überschreiben Sie immer gleich ()? Wenn ja, tust du auch hashcode ()? toString ()? Machen Sie es sich zur Gewohnheit, die vergleichbare Schnittstelle zu implementieren?
Ich habe gerade einen Code geschrieben, wo ich compareTo () implementieren und equals () überschreiben musste, damit mein Programm vernünftig funktioniert; Ich sehe jetzt Wege, diese überall zu benutzen ...
Was denkst du?
Normalerweise implementiere ich Dinge nicht im Voraus, es sei denn, ich brauche sie.
Wenn meine Klasse Datenelemente enthält und ich beabsichtige, sie irgendwo zu speichern, werde ich normalerweise equals, hashCode und vergleichbar implementieren.
Allerdings habe ich festgestellt, dass die meisten meiner Klassen dieses Problem nicht haben, also macht es keinen Sinn, es zu tun. Wenn sich beispielsweise in Ihrer Klasse die Funktionalität anderer Objekte als Daten dreht, warum sollten Sie sich die Mühe machen? Wenn Sie eine Instanz haben oder hierarchisch organisiert sind (z. B. ein GUI-Widget oder -Fenster), warum sollten Sie sich die Mühe machen?
Implementieren Sie keine Dinge, die Sie nicht benötigen, aber überprüfen Sie immer, ob sie benötigt werden oder nicht, da Java Sie normalerweise nicht warnt.
Stellen Sie außerdem sicher, dass Sie Ihre IDE oder etwas wie Apache commons verwenden, um diese Funktionen zu generieren. Es gibt selten eine Notwendigkeit, sie von Hand zu codieren.
Wie bei toString, implementiere ich es selten, bis ich mich selbst im Debugger finde und eine bessere Darstellung im Eclipse-Debugger benötige (z. B. anstelle der Objekt-ID). Ich habe Angst vor impliziten Konvertierungen und verwende nie toString beim Generieren von Ausgaben.
Wenn Sie equals
überschreiben, müssen Sie (fast immer) hashCode
überschreiben. Der Vertrag von hashCode
besteht darin, dass zwei Objekte, die gleich sind, denselben Hash-Code haben müssen. Wenn Sie equals überschreiben, so dass die Gleichheit auf etwas neben dem Systemidentitätshashcode basiert, ist es möglich, dass zwei Objekte gleich sind, aber einen unterschiedlichen Hashcode haben.
Ich denke, du solltest niemals Dinge umsetzen, die du nicht brauchst, oder bist dir nicht sicher, ob du sie brauchen wirst oder nicht. Wenn Sie Ihrem Code keinen Mehrwert hinzufügen, fügen Sie ihn nicht ein. Wenn Sie Ihre (Unit-) Tests synchron mit Ihrem Code halten und diese verwenden möchten, um Anwendungsfälle Ihres Codes anzuzeigen, sollten Sie dies nicht tun alles haben, was nicht durch diese Tests abgedeckt ist. Dazu gehören equals (), hashCode (), compareTo () usw.
Das Problem, das ich sehe, außer einer möglichen Zeitverschwendung, ist, dass es jemanden verwirrt, der den Code liest. "Warum hat diese Klasse equals implementiert? Ist es ein Datenwert? Kann es Teil einer Sammlung sein? Ist es sogar sinnvoll, Instanzen dieser Klasse zu vergleichen?"
Ich würde also sagen, dass Sie diese nur implementieren, wenn Sie sie wirklich brauchen. Deshalb kann ich nicht sagen, dass ich diese und diese Methode immer umsetze. Vielleicht wäre toString () die Methode, die ich am meisten schreibe, weil es beim Debuggen sehr nützlich ist.
Fast immer toString () ist es ein Problem zu debuggen und etwas über das Objekt Class @ 123456
zu lesenequals () und hashCode () bei Bedarf, aber immer beides oder keines.
Die Iterable-Schnittstelle ist für sammlungsähnliche Klassen nützlich und liefert normalerweise nur etwas wie innerCollection.iterator (). Vergleichbar kann auch nützlich sein.
Außerdem hat unser Unternehmen einige Schnittstellen erstellt, die ich oft verwende, wie Displayable (wie toString, aber mehr oder andere Arten von Informationen, wie zum Beispiel für Logging) und ParseLocatable (für Dinge, die aus einer Datei stammen, die wir analysieren, und wir wollen um zu sehen in welcher Datei und in welcher Zeile zB eine bestimmte Regel definiert wurde (ein wenig wie Stacktraces)
Effektives Java hat ein Kapitel darüber, wie und wann toString, equals, hashCode, Comparable, etc Sehr empfehlenswert zum Lesen.
toString()
ist manchmal sehr hilfreich für Testzwecke, wenn Sie zu faul sind, Komponententests zu schreiben. Dies ist auch praktisch für watches beim Debuggen.
Aber ich würde nicht empfehlen, Comparable
in jedem Objekt zu implementieren, es ist manchmal schön, aber benutze es weise oder du wirst mit viel Code enden, den du nicht wirklich brauchst.
Dito für toString()
und seine Varianten in verschiedenen Sprachen und Laufzeiten, aber ich möchte Sie auch auf Ned Batchelders Artikel auf stringification , was eine gute Lektüre ist und meiner Argumentation sehr nahe kommt.
Für geschäftliche CRUD-Anwendungen überschreibe ich immer ToString. Dies hilft beim Binden einer List (Of T) an ein WinForm-Steuerelement. Wenn Sie beispielsweise ToString in einem Customer-Objekt überschreiben, um _name zurückzugeben, wird der Wert des Kundennamens beim Binden einer List (Of Customer) an ein ListBox-Steuerelement automatisch angezeigt. Kommt praktisch.
Normalerweise implementiere ich die Methode compareTo
sowie die Methode toString
. Es ist im Allgemeinen gut zu wissen, wie eine Instanz der Klasse für Sortierungen und Suchen mit einer anderen Instanz verglichen wird. Auch eine überlagerte toString-Methode eignet sich hervorragend zum Debuggen. Sie können den Inhalt der Klasse (nicht nur den Speicherort) auf eine Weise sehen, die für die Klasse, die Sie geschrieben haben, sinnvoll ist.
Bei Objekten, die hauptsächlich zum Halten von Daten verwendet werden ("rockt"), finde ich toString und den equals / hashcode-Vertrag als unschätzbar wertvoll. Der Grund dafür ist, dass Steine in der Regel in Sammlungen hinein- und herausgezogen werden, vor allem die Hash-Sammlungen (Set / Map), die den equals- und hashcode-Vertrag erfordern, und es ist sehr einfach, diese Objekte in toString in einem Debugger zu sehen ist implementiert. Bei der Implementierung von toString verwende ich immer die ToStringBuilder-Klasse von Apache Common, um alle meine Eigenschaften anzuzeigen - auf diese Weise ist es sehr einfach, die Ausgabe zu lesen. Ich bin nie besorgt über "implizite Konvertierung" - toString ist nicht als etwas anderes als eine menschlich lesbare Zeichenfolge, dass die toString kann auf Anzahl Unterklassen verwendet werden, um in und aus zu konvertieren ist wirklich nur eine Marotte, etc. Produktionscode sollte Verlassen Sie sich niemals auf die toString-Methode, um das Objekt in eine String-Repräsentation zu konvertieren, weil das nicht der Fall ist - es ist für eine lesbare String-Repräsentation, also sollte eine andere Methode definiert werden, wenn ein nicht-menschlicher, Es ist jedoch eine Computercode verwendbare Zeichenfolgendarstellung erwünscht.
Für Datenwertklassen habe ich eine AbstractPojo-Klasse, die Reflektion zur Implementierung von equals, hashCode, toString und asMap () verwendet
Ich erweitere diese Klasse für alle meine Datenwertobjekte, also implementiere ich das nicht jedes Mal.
Ich überschreibe nicht ToString, aber ich verwende manchmal das DebuggerDisplay-Attribut, das das gleiche für die Debugging-Zwecke tut und die Freigabeversion nicht belastet.
Ich habe auch festgestellt, dass ich die ToString () -Methode oft übersteuert habe. Besonders während der Entwicklung. Obwohl Code-Generatoren helfen, wird es ziemlich nervig, sie jedes Mal ändern zu müssen, wenn ein Klassenmitglied umbenannt wird. Eigentlich war ich so genervt, ich habe versucht, Abhilfe zu schaffen. Das ist es, was ich mir ausgedacht habe:
Erstellt eine Zeichenfolge dieses Formats: MemberType MemberName = MemberValue
Verwendung:
%Vor%Schreibt die Zeichenfolge testMember="testing" in die Konsole. Hier ist es:
%Vor%Eine ausführlichere Erklärung und wie man es benutzt, finden Sie in meinem Blog über: Generische ToString () Methode
Tags und Links java