double dispatch und equals(Object)

hierUndDa

Mitglied
Hallo zusammen

Ich habe mich gerade etwas mit equals() rumgeschlagen. Ich hätte es im Grund gerne als double dispatch implementiert. Dies klappt auch solange ich mein eigenes Interface verwende.

Sobald ich jedoch meine Objekte einem Object zuweise, kriege ich eine StackOverflow Exception. Ein explizites cast vor this bringt ebenfalls nichts (Zeile 16 & Zeile 47).

Weiss jemand weshalb?

Java:
package examples;

public class SimpleDoubleDispatch {
}

interface IWoman {
	public boolean equals(Object obj);
	public boolean equals(IWoman woman);
	public boolean equals(Woman woman);
	public boolean equals(BeardedWoman beardedWomen);
}

class BeardedWoman implements IWoman {
	@Override
	public boolean equals(Object obj) {
		return obj.equals(this);
	}
	@Override
	public boolean equals(Woman woman) {
		return woman == null ? false : true;
	}
	@Override
	public boolean equals(IWoman obj) {
		return obj.equals(this);
	}
	@Override
	public boolean equals(BeardedWoman bearded) {
		return bearded == null ? false : true;
	}
}

class Woman implements IWoman {
	@Override
	public boolean equals(BeardedWoman bearded) {
		return bearded == null ? false : true;
	}
	@Override
	public boolean equals(Woman woman) {
		return woman == null ? false : true;
	}
	@Override
	public boolean equals(IWoman woman) {
		return woman.equals(this);
	}
	@Override
	public boolean equals(Object obj) {
		return obj.equals(this);
	}
}

Hier die Testklasse dazu. Wie gesagt, die drei letzten Tests fallen wegen einer StackOverflow Exception durch.

Java:
package examples;

import static org.junit.Assert.*;

import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import org.junit.Test;

@RunWith(JUnit4.class)
public class TestDoubleDispatch {
	
	@Test
	public void womanShouldBeEqualToItSelf() {
		Woman woman = new Woman();
		assertTrue(woman.equals(woman));
	}
	
	@Test
	public void womanAsIWomanShouldBeEqualToItSelf() {
		IWoman woman = new Woman();
		assertTrue(woman.equals(woman));
	}
	
	@Test
	public void womanAndNullShouldNotBeEqual() {
		Woman woman = new Woman();
		Woman woman2 = null;
		assertFalse(woman.equals(woman2));
	}
	
	@Test
	public void womanAndBeardedWomenShouldBeEqual() {
		Woman woman = new Woman();
		BeardedWoman bearded = new BeardedWoman();
		
		assertTrue(woman.equals(bearded));
		assertTrue(bearded.equals(woman));
	}
	
	@Test
	public void womanAndBeardedWomanAsIWomanShouldBeEqual() {
		Woman woman = new Woman();
		IWoman bearded = new BeardedWoman();
		
		assertTrue(woman.equals(bearded));
		assertTrue(bearded.equals(woman));
	}
	
	@Test
	public void womanAsIWomanAndBeardedWomanAsIWomanShouldBeEqual() {
		IWoman woman = new Woman();
		IWoman bearded = new BeardedWoman();
		
		assertTrue(woman.equals(bearded));
		assertTrue(bearded.equals(woman));
	}
	
	@Test
	public void womanAsObjectShouldBeEqualToItSelf() {
		Object woman = new Woman();
		assertTrue(woman.equals(woman));
	}
	
	@Test
	public void womanAsObjectAndBeardedWomanShouldBeEqual() {
		Object woman = new Woman();
		BeardedWoman bearded = new BeardedWoman();
		
		assertTrue(bearded.equals(woman));
		assertTrue(woman.equals(bearded));
	}
	
	@Test
	public void womanAsObjectAndBeardedWomanAsObjectShouldBeEqual() {
		Object woman = new Woman();
		Object bearded = new BeardedWoman();
				
		assertTrue(bearded.equals(woman));
		assertTrue(woman.equals(bearded));
	}
}
 

tfa

Top Contributor
public boolean equals(Object obj) {
return obj.equals(this);
}
Das ist nunmal eine Endlosschleife, wenn obj von der Klasse Woman ist.
Lass equals() am besten von der IDE generieren oder verwende einen EqualsBuilder.
Viele equals-Methoden zu überladen halte ich für nicht sinnvoll.
 

hierUndDa

Mitglied
Ich find das nicht so logisch, wie du es jetzt beschreibst.

Wenn obj von der Klasse Woman ist, dann weiss das obj doch. Das bedeutet, es wird in Woman die Klasse equals() aufgerufen, da ich als Argument this übergebe, sollte doch dann auch klar sein, was ich übergebe.

Ich stelle mir das so vor:

Java:
Object woman = new Woman();
Object beardedWoman = new BeardedWoman();

Java:
woman.equals(beardedWoman);
=> woman weiss welche equals Methode zu ihr passt und ruft deshalb Woman#equals(Object obj) auf, da sie nicht weiss, dass beardedWoman eine BeardedWoman ist. Im Woman#equals(Object obj) stell ich mir den Aufruf dann so vor:

Java:
beardedWoman.equals(this);
=> this ist nun klar ein Woman Objekt, also sollte doch in BeardedWoman die Methode BeardedWoman#equals(Woman woman) aufrufen und nicht BeardedWoman#equals(Object obj)?

Irgendwas habe ich grundsätzlich noch nicht begriffen... Ich würde gerne wissen, weshalb sich das ganze nicht so verhält, wie ich mir das vorstelle.
 

Wildcard

Top Contributor
Java ist eine Single Dispatch Sprache, das kann so also nicht funktionieren. Du müsstest das Argument explizit casten damit es in einer spezifischeren Methode landet.
Viele equals-Methoden zu überladen halte ich für nicht sinnvoll.
Absolut, das ist eine ganz schlechte Idee und jetzt solltest du auch wissen warum...
 

hierUndDa

Mitglied
Der Hinweis Single-Dispatch hat geholfen.

PS: Auch ein explizites Casting nützt nichts, z.B. obj.equals((Woman) this). Java ist nicht in der Lage in Subklassen überladene Methoden aufzurufen.

Java:
package examples;

public class JavaDispatch {
	public static void main(String[] args) {
		Human human = new Human();
		Human sam = new Sam();
		
		sam.meet(human);
		sam.meet(sam);
		sam.meet((Sam) sam);
	}
}

class Human {
	public void meet(Human hu) {
		System.out.println("Human meets Human");
	}
}

class Sam extends Human {
	public void meet(Sam sam) {
		System.out.println("Sam meets Sam");
	}
}

Code:
Output:
Human meets Human
Human meets Human
Human meets Human
 

Wildcard

Top Contributor
So:
Java:
((Sam)sam).meet((Sam) sam);

Wenn du es anders schreibst reicht auch der einfache cast:

Java:
package examples;
 
public class JavaDispatch {
    public static void main(String[] args) {
        Human human = new Human();
        Human sam = new Sam();
        
        sam.meet(human);
        sam.meet(sam);
        sam.meet((Sam) sam);
    }
}
 
class Human {
    public void meet(Human hu) {
        System.out.println("Human meets Human");
    }
    
    public void meet(Sam sam) {
        System.out.println("Sam meets Sam");
    }
}
 
class Sam extends Human {

}

Solche Konstrukte sollte man nach Möglichkeit vermeiden, denn es entstehen leicht Fehler (wohl auch weil viele Entwickler das Konzept nicht vollständig verstehen).
In Java verwendet man statt Double Dispatch normalerweise das Visitor Pattern.

Frage: Multiple Dispatch ist in den meisten modernen Programmiersprachen nicht direkt vorgesehen. Von welcher Programmiersprache kommst du ursprünglich?
 
Zuletzt bearbeitet:

hierUndDa

Mitglied
Danke für deine Antwort.

Es war ein Teil einer Vorlesung über Java. Ich wollte einfach das Konzept verstehen, weil ich es spannend fand.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
JAnruVA Datentypen Berechneten String-Wert in Double umwandeln um weiter zu rechnen Allgemeine Java-Themen 7
Neumi5694 double Vergleich Allgemeine Java-Themen 19
G Modulo - double Allgemeine Java-Themen 21
ReinerCoder Eclipse Fehlermeldung - The constructor Double(double) is deprecated Allgemeine Java-Themen 8
O Variablen Addition von Double-Werten ergibt seltsame 0.9999999 Zahlen Allgemeine Java-Themen 2
B Long in einen Double umwandeln und im Label anzeigen Allgemeine Java-Themen 7
VfL_Freak Double mit zwei festen NK-Stellen ausgeben Allgemeine Java-Themen 9
B List<Integer> ist List<Double> ? Allgemeine Java-Themen 6
SkyScreamer Variablen Int umwande in Double/ 1 Miner = 5 Cookies/s Allgemeine Java-Themen 2
T Teile eines Double-Wertes verändern Allgemeine Java-Themen 2
T Double salted bcrypt Allgemeine Java-Themen 0
A Zahl abgerundet obwohl Double Allgemeine Java-Themen 9
R jTable, nur Werte zwischen 2 Double values ausgeben Allgemeine Java-Themen 3
Y String to Double ohne ParseDouble Allgemeine Java-Themen 11
D Double aus String auslesen Allgemeine Java-Themen 8
M double Array Allgemeine Java-Themen 8
P Wird double und float auf jedem Computer gleich berechnet? Allgemeine Java-Themen 10
C String in double[][] konvertieren! Allgemeine Java-Themen 5
M Cast double[]-->Object[] oder Vector<double[]> Allgemeine Java-Themen 3
Zettelkasten Double --> Integer Allgemeine Java-Themen 4
M float, double, BigDecimal Allgemeine Java-Themen 5
S Variablen Prüfen ob Number vom Typ Integer, Float, Double, ... ist Allgemeine Java-Themen 2
J String mit "," in Double Wert konvertieren Allgemeine Java-Themen 7
R Eclipse Verschiedene Ergebnisse bei Berechnung eines double-Werts Allgemeine Java-Themen 5
B Variablen Bug of Float. & Double.MIN_VALUE! Allgemeine Java-Themen 4
T ArrayList<double[]> persitent anlegen Allgemeine Java-Themen 7
K double Zufallszahl Allgemeine Java-Themen 6
S String in Double - letztes Zeichen fehlt Allgemeine Java-Themen 4
T int <-> integer, double <-> Double... Allgemeine Java-Themen 2
J Umstellung von double auf BigDecimal Allgemeine Java-Themen 5
H2SO3- String 1.000,00 in double umwandeln Allgemeine Java-Themen 12
S Double-Checked Locking Allgemeine Java-Themen 4
I 2D-Grafik Polygon mit Double Werten zeichnen Allgemeine Java-Themen 4
M FIFO Queue: bytes in, float/double/etc out Allgemeine Java-Themen 5
vandread Float/Double probleme bei der Multiplikation?! Allgemeine Java-Themen 3
J Casting Problem Object, Double und String Allgemeine Java-Themen 3
F double auf 2 Nachkommastellen runden Allgemeine Java-Themen 9
D Double to Integer - ist das möglich? Allgemeine Java-Themen 3
T Object auf Double, Int, String testen Allgemeine Java-Themen 5
H2SO3- großen double in string mit e umwandeln Allgemeine Java-Themen 4
T Problem: Double als Geldbetrag - Rundungsfehler Allgemeine Java-Themen 5
P große double Zahlen und modulo Allgemeine Java-Themen 8
G Double Wert über OutputStream verschicken Allgemeine Java-Themen 2
M größer als double? Allgemeine Java-Themen 4
N Double ohne Wissenschaftliche Schreibweiße Allgemeine Java-Themen 5
M Double Braces Notation um Collections zu initialisieren Allgemeine Java-Themen 9
R Eigene ArrayList vom Typ Short, Integer oder Double Allgemeine Java-Themen 4
R Double Werte aus byte[] auslesen Allgemeine Java-Themen 5
T XStream.toXML => double mit , anstelle . Allgemeine Java-Themen 3
G Fehler bei Array.getDouble mit Double[] als Argument! Allgemeine Java-Themen 6
A Problem bei Übergabe von Werten in ein double Array. Allgemeine Java-Themen 21
M Double immer mit 2 Kommastellen Allgemeine Java-Themen 3
G double in Date Allgemeine Java-Themen 5
reibi double-Wert auf 2 Stellen nach dem Komma abschneiden Allgemeine Java-Themen 6
G Genauigkeit von Double Allgemeine Java-Themen 2
F Double mit Streams aus Datei einlesen Allgemeine Java-Themen 3
V "double in Exponentialschreibweise" normal ausgebe Allgemeine Java-Themen 2
S List<Double> oder Double[] in double[] zu konvertieren Allgemeine Java-Themen 6
C casten vom Typ Object nach Double[][] Allgemeine Java-Themen 2
E int vs. float vs. double Allgemeine Java-Themen 7
T cast Object to Double[] Allgemeine Java-Themen 2
DEvent double von c nach Java Allgemeine Java-Themen 4
K Double-Zahl runden Allgemeine Java-Themen 4
J double 3.0 soll ohne Nachkommastelle ausgegeben werden Allgemeine Java-Themen 12
S Java Double addieren Allgemeine Java-Themen 3
A string zu double Allgemeine Java-Themen 3
T double to object Allgemeine Java-Themen 3
J Große Zahl (double) as text ausgeben? Allgemeine Java-Themen 2
G Verständnisproblem double und float Allgemeine Java-Themen 7
padde479 String in double parsen Allgemeine Java-Themen 6
E double auf int runden, nicht abschneiden Allgemeine Java-Themen 2
G Double Zahl quadrieren Allgemeine Java-Themen 8
C double Zahlen mit drei NachkommaStellen in String umwandeln Allgemeine Java-Themen 2
T Nachkommastellen double Allgemeine Java-Themen 18
M double aufrunden Allgemeine Java-Themen 6
W Division mit float und double Allgemeine Java-Themen 2
D JTextfield für double werte Allgemeine Java-Themen 2
S Format von Double Allgemeine Java-Themen 9
F Umwandlungsproblem mit double Allgemeine Java-Themen 2
S Problem! Lösung mit Double buffering Allgemeine Java-Themen 3
T Vector <-> double Allgemeine Java-Themen 4
W float/double verhält sich seltsam Allgemeine Java-Themen 6
D Double: Grenzen und Darstellung Allgemeine Java-Themen 7
W String to Double (landesspezifisch) Allgemeine Java-Themen 14
T Fließkomma (double) richtig runden Allgemeine Java-Themen 7
P Class zu Integer, String, Double etc. Allgemeine Java-Themen 11
R Fehler in WindowsXP oder Java? - double in int konvertieren Allgemeine Java-Themen 10
E NumberFormatException bei cast auf double Allgemeine Java-Themen 5
D Wann ist das ergebnis einer Rechnung eine Double? Allgemeine Java-Themen 7
G Double Zahl auf 4 Stellen hinter Komma kuerzen Allgemeine Java-Themen 4
G warum operator || cannot be applied to int, double Allgemeine Java-Themen 11
A Probleme Umwandlung Ausdruck String in double Allgemeine Java-Themen 4
B Double-Wert aus einem HexString erstellen. Allgemeine Java-Themen 11
R Double Buffering zu langsam Allgemeine Java-Themen 11
C Bug in Java1.4.2_03 mit double Allgemeine Java-Themen 5
H Double mit 2 Nachkommastellen speichern. Allgemeine Java-Themen 5
C Double zu Hex oder Byte Allgemeine Java-Themen 4
K event dispatch thread fehler. Compiler meckert nicht aber der Interpreter? Warum?? Allgemeine Java-Themen 11
mihe7 equals und instanceOf pattern matching Allgemeine Java-Themen 9
P Strings: equals vs == Allgemeine Java-Themen 47

Ähnliche Java Themen

Neue Themen


Oben