equals - Identität ändern bei Vererbung?

Shiwayari

Mitglied
Bin gerade auf ein kleines (?) Designproblem gestoßen:

Ich habe Entry Objekte, die in einem Set gelagert werden, und deren equals/hashCode Methoden so überschrieben sind, dass die Identität nur vom Attribut name abhängt.

Weiter habe ich Objekte TitledEntry, die das gleiche sind wie ein Entry, zusätzlich aber ein Attribut title und zugehörige Methoden haben.

Nun soll aber ein beliebiges Entry Objekt ungleich eines beliebigen TitledEntry Objekts sein; der Titel ändert also die Identität des Entry's.



Da ich ein TitledEntry genauso benutzen will, wie ein Entry, macht erben von Entry eigentlich Sinn..
In TitledEntry überschreibe ich dann die equals/hashCode Methoden so, dass sie Name und Titel
miteinbeziehen...

Und dann bekomme ich sowas:

Java:
Entry e = new Entry("Name");
TitledEntry t = new TitledEntry("Name", "Title");

//Soll beides false ergeben:
e.equals(t) // ergibt true
t.equals(e) // ergibt false

Und das is ja vollkommen wirr.


Ich könnte folgendes machen:

Entweder
1) Ich überprüfe in der equals Methode der Entry Klasse, ob das übergebe Objekt ein Entry oder ein TitledEntry ist.

Oder
2) Ich lasse TitledEntry nicht von Entry erben, sondern erstelle in TitledEntry ein Attribut vom Typ Entry; und leite dann alle Methoden auf das Attribut um..


Beides blöd =/
Bei 1) muss die Oberklasse von der Unterklasse wissen, was nicht sonderlich sinnvoll ist, dann kann ich auch gleich das Attribut title in die Oberklasse reinnehmen.

Und 2) ist wie ich finde sehr umständlich und unsauber.


Im Prinzip könnte ich schon das zusätzliche Attribut title mit in die Oberklasse schreiben, aber was ist wenn ich nicht nur 1 Attribut hinzufügen will, sondern ganz viele?
Dann habe ich in der Oberklasse etliche Attribute, die nie benutzt werden, das will ja auch niemand.


Bessere Lösungsvorschläge?
 
Ich hab das mal testweise selbst ausprobiert und keine Probleme gehabt.

Edit: Quatsch erzähl ich. Hab das selbe Problem. 🙂

Edit2: Machst du die Überprüfung in der equals-Methode mit einem instanceof? Dann ist es klar, dass da im ersten Fall true kommt. Stattdessen könntest du direkt überprüfen, ob das Objekt mit dem verglichen wird, auch tatsächlich vom gleiche Typ ist. Meine Klasse heißt hier TestObject:

Java:
@Override
	public boolean equals(Object arg0) {
		if (arg0.getClass().equals(this.getClass()))
			return ((TestObject) arg0).name.equals(name);
		return false;
	}
 
Zuletzt bearbeitet von einem Moderator:
Übrigens: Eclipse hat dazu schon einen guten Mechanismus.
Code:
Source > Generate hashCode() and equals()... > "Use 'instanceof' to compare types" deaktivieren

Ergibt bei mir (hashCode() mal weggelassen):
Java:
public class Entry {
	private final String name;

	public Entry(final String name) {
		this.name = name;
	}

	public final String getName() {
		return name;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Entry other = (Entry) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}
Java:
public class TitledEntry extends Entry {
	private final String title;

	public TitledEntry(final String name, final String title) {
		super(name);
		this.title = title;
	}

	public final String getTitle() {
		return title;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		TitledEntry other = (TitledEntry) obj;
		if (title == null) {
			if (other.title != null)
				return false;
		} else if (!title.equals(other.title))
			return false;
		return true;
	}

	public static void main(String[] args) {
		final Entry e = new Entry("Name");
		final TitledEntry t = new TitledEntry("Name", "Title");

		// Soll beides false ergeben:
		System.out.println(e.equals(t)); // ergibt false
		System.out.println(t.equals(e)); // ergibt false
	}
}

PS: Ich finde deinen zweiten Ansatz (Entry als Instanzvariable von TitledEntry) gar nicht so verkehrt.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben