Interface Equals und hashCode

Schuriko

Bekanntes Mitglied
Gibt es eigentlich in Java ein vordefiniertes Interface, was kenntlich macht, dass eine Klasse über die Methoden equals und hashCode verfügt?
 
Oder ist die Frage (auch) so zu verstehen, dass eine Klasse über eine eigene/überschriebene Implementierung von equals() und hashCode() verfügt ?
 
Oder ist die Frage (auch) so zu verstehen, dass eine Klasse über eine eigene/überschriebene Implementierung von equals() und hashCode() verfügt ?
In dem Fall kann man Reflection nutzen.

a) Refrerenz auf die Klasse (Klassenname.class oder instance.getClass()) holen.
b) auf der Klasse mit getMethod die Methode holen.
c) auf der Methode getDeclaringClass aufrufen und mit Klasse aus a) vergleichen.
 
Da würde ich eher eine Annotation machen, welche das prüft und zur compile Zeit einen Fehler wirft. (Oder gar nichts, sauber mit Tests sollte man da ja sowieso keinen Fehler haben)

Ich sehe nämlich gerade keinen Grund, warum das zu Laufzeit geprüft werden müsste
 
Mich würde auch mal der Kontext bzw. Grund der Frage interessieren.
Also der Grund ist folgender: Ich habe in einem Objekt ein Attribut welches drei unterschiedliche Klassen sein können. Hier mal etwas vereinfacht shematisch dargestellt:

Code:
class Container {
    Object aufnahme;              // Aufnahme nur für ClassA, ClassB, ClassC nicht ClassD
}

class ClassA {
     ....
}

class ClassB {
     ....
}

class ClassC {
     ....
}

class ClassD {
     ....
}
Die Kontainer Klasse soll es zulassen, dass ClassA, ClassB und ClassC (die nicht voneinander abgeleitet sind) aufnehmen kann.
Die ClassD ist hierfür nicht erlaubt.
 
Wie kommt man zu so einem Konstrukt?

Also ich finde es zumindest seltsam und ich frage mich gerade, was für Operationen du darauf machen willst / musst....

Du kannst da 3 Setter und 3 Getter bauen. Dann kannst du dank polymorphie nur die drei erlaubten Dinge zuweisen. Getter ist aber blöd, da hast du dann ggf 3 unterschiedliche Namen....

Aber da würde ich erst einmal das Design in Frage stellen / hinterfragen ....
 
Kannst du evtl. die Klassen A, B und C mit einem Marker-Interface versehen? Oder sind die von dir nicht veränderbar?
Java:
interface ContainerObject {}

class Container {
    ContainerObject aufnahme;              // Aufnahme nur für ClassA, ClassB, ClassC nicht ClassD
}

class ClassA implements ContainerObject {
     ....
}

class ClassB implements ContainerObject {
     ....
}

class ClassC implements ContainerObject {
     ....
}

class ClassD {
     ....
}

Das macht aber die spätere Verwendung auch nicht leichter...

EDIT: Aber was hat das eigentlich mit equals() und hashCode() zu tun?
 
Zuletzt bearbeitet:
Kannst du evtl. die Klassen A, B und C mit einem Marker-Interface versehen? Oder sind die von dir nicht veränderbar?
Java:
interface ContainerObject {}

class Container {
    ContainerObject aufnahme;              // Aufnahme nur für ClassA, ClassB, ClassC nicht ClassD
}

class ClassA implements ContainerObject {
     ....
}

class ClassB implements ContainerObject {
     ....
}

class ClassC implements ContainerObject {
     ....
}

class ClassD {
     ....
}

Das macht aber die spätere Verwendung auch nicht leichter...

EDIT: Aber was hat das eigentlich mit equals() und hashCode() zu tun?
Das hatte ich auch vor. Deshalb kam ich darauf, ob equals, hash, clone funktion basiert. Momentan habe ich ein "abstrakt" Interface um diese Klassen kenntlich zu machen.
 
Wie kommt man zu so einem Konstrukt?

Also ich finde es zumindest seltsam und ich frage mich gerade, was für Operationen du darauf machen willst / musst....

Du kannst da 3 Setter und 3 Getter bauen. Dann kannst du dank polymorphie nur die drei erlaubten Dinge zuweisen. Getter ist aber blöd, da hast du dann ggf 3 unterschiedliche Namen....

Aber da würde ich erst einmal das Design in Frage stellen / hinterfragen ....
Nun leider sieht es W3C anders. Für die HTML Canvas gibt es ein fillStyle / strokestyle, welches wahlweise Farbe, Gradient oder Image sein kann.
 
Nun leider sieht es W3C anders. Für die HTML Canvas gibt es ein fillStyle / strokestyle, welches wahlweise Farbe, Gradient oder Image sein kann.
Ne, das widerspricht der Aussage von @JustNobody nicht 🙂

Das ist dann halt ein Interface "StrokeStyle" (oder wie auch immer man sie nennen möchte), das muss ja dann nicht mal leer sein.


Ein Pendant aus JavaFX wäre dazu zB https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/Border.html, das ist auch eine mögliche Variante.


Das hatte ich auch vor. Deshalb kam ich darauf, ob equals, hash, clone funktion basiert. Momentan habe ich ein "abstrakt" Interface um diese Klassen kenntlich zu machen.
Aber equals und hash hat doch jedes Objekt, was war denn die Idee dahinter, wie es damit eingeschränkt werden soll?
 
Ja, wie mrBrown das schon richtig gesagt hat: Dann ist das so ein Style und das kann dann ein Interface sein. Und schon hast Du auch das, was temi vorgeschlagen hat. So etwas sollte man aus meiner Sicht auf jeden Fall haben.
 
Noch als Anmerkung: in anderen Sprachen könnte man das zB über Union-Types abbilden, in Java könnten Sealed-Types interessant sein, wobei man dafür dann auch das Interface braucht.
 
Leider nein, habe ich mir auch schon oft gewünscht. Das Fehlen eines solchen Interface ist nach meiner Meinung ein Geburtsfehler von Java.
Das Problem ist dann doch eher, dass java.lang.Object bereits die Methoden equals()/hashCode() implementiert, und nicht, dass es kein solches Interface gibt (bzw. geben kann). Die blosse Existenz einer "eigenen" equals()/hashCode() Implementierungsmethode sagt ja nichts darüber aus, wie diese implementiert ist:
Java:
public class MyOwnClass implements WithHashCodeAndEquals {
  public int hashCode() {
    return super.hashCode();
  }
  public boolean equals(Object o) {
    return super.equals(o);
  }
}
Warum würde jemals jemand wissen wollen, ob eine Klasse eine eigene equals()/hashCode() Überschreibung hat?
Wahrscheinlich ist es manchmal wichtig, zu wissen, ob die Gleichheit zweier Instanzen einer Klasse auf der Objektidentität oder auf einem Wertevergleich (im Sinne eines "value objects") basiert. Das könnte ich mir vorstellen. Das hat aber ja nichts damit zu tun, ob es nun equals()/hashCode() gibt, oder nicht, da man diese ja wie gesagt beliebig implementieren kann.
 
@httpdigest Du hast es genauer formuliert als ich, java.lang.Object sollte nicht hashCode und equals implementieren (eventuell sollte es java.lang.Object gar nicht geben). Ein entsprechendes Interface würde eine eigene Implementierung erzwingen, diese kann aber auch fehlerhaft sein.
 

Zurück
Oben