Instanceof außerhalb der equals-Methode: Unterschied zwischen den Versionen

Aus Programmieren-Wiki
(Die Seite wurde neu angelegt: „{{Bewertungsrichtlinie |baustelle=Ja |blatt=1 |schweregrad=leicht |weiterlesen=Nein }}“)
 
(Positivbeispiel für Polymorphie statt instanceof (Siehe https://gitlab.kit.edu/kit/kastel/sdq/lehre/programmieren-vorlesung/gruppen/programmieren-tutoren/wiki-issues/-/issues/3))
 
(9 dazwischenliegende Versionen von 5 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
{{Bewertungsrichtlinie
{{CategoryBlock
|baustelle=Ja
|Baustelle=Ja
|blatt=1
|Java Grundlagen=Nein
|schweregrad=leicht
|Organisation=Nein
|weiterlesen=Nein
|Programmierstil=Nein
|Bewertungsrichtlinie=Ja
|blattAnnotation=1
|blattAbzug=2
}}
{{Inhaltsblock
|vorher==== Beschreibung===
Die Java API bietet uns das Schlüsselwort <syntaxhighlight inline lang="Java">instanceof</syntaxhighlight>, um zu prüfen, ob eine Objekt eine Instanz einer bestimmten Schnittstelle (Interface) oder Klasse ist.
 
In aller Regel kann die Verwendung von <syntaxhighlight lang="Java" inline>instanceof</syntaxhighlight> durch den Einsatz von Polymorphie umgangen werden, das heißt, man definiert eine Methode in der Oberklasse/im Interface, von dem alle betroffenen Klassen erben, die das gewünschte Verhalten umsetzt. Die Verwendung von <syntaxhighlight lang="Java" inline>instanceof</syntaxhighlight> gilt daher als äußerst schlechter Stil.
 
Im Rahmen dieses Übungsbetriebs ist die Verwendung von <syntaxhighlight lang="Java" inline>instanceof</syntaxhighlight> somit unzulässig.
 
Eine einzige Ausnahme besteht in der Implementierung der [https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object- equals(Object o)]-Methode einer Klasse. Üblicherweise prüft man in eigenen Implementierungen von <syntaxhighlight lang="Java" inline>equals</syntaxhighlight> zuallererst, ob das "andere" Objekt <syntaxhighlight lang="Java" inline>null</syntaxhighlight> ist, und wenn nicht, ob eine Instanz der entsprechenden Klasse ist. Diese beiden Prüfungen sind in einer <syntaxhighlight lang="Java" inline>instanceof</syntaxhighlight>-Abfrage möglich, wie im Positivbeispiel beschrieben. Zu diesem Zweck ist der Einsatz von <syntaxhighlight lang="Java" inline>instanceof</syntaxhighlight> erlaubt.
}}
{{Inhaltsblock
|color=red
|vorher=Negativbeispiel:
|Beispiel=public void talk(Person[] persons) {
for (Person person : persons) {
if (person instanceof InfoStudent) {
System.out.println("Ich studiere Informatik …");
} else if (person instanceOf Employee) {
System.out.println("Ich arbeite in der Industrie …");
}
}
}
|beispielname=InstanceofBad
|nachher=Hier bestimmen <syntaxhighlight lang="Java" inline>instanceof</syntaxhighlight>-Abfragen das gewünschte Verhalten. Eine viel bessere Lösung wäre es hier, in der Klasse Person eine abstrakte Methode zu definieren, die einen String zurück- oder ausgibt. Diese Methode sollte dann von der Employee und InfoStudent Klasse geerbt und implementiert werden.
}}
{{Inhaltsblock
|color=green
|vorher=Positivbeispiel
|Beispiel=abstract class Person {
public abstract String getActivity();
}
 
class InfoStudent extens Person {
@Override
public String getActivity() {
return "Ich studiere Informatik";
}
}
 
class Employee extends Person {
@Override
public String getActivity() {
return "Ich arbeite in der Industrie";
}
}
 
//...
public void talk(Person[] persons) {
for (Person person : persons) {
System.out.printf("%s …%n", person.getActivity());
}
}
|beispielname=instanceOfReplacement
|nachher=Hier wird Vererbung genutzt um das gleiche Ergebnis zu erreichen wie oben. Durch die Verwendung von Vererbung wird das Projekt deutlich erweiterbarer, da beim Hinzufügen neuer Unterklassen von <syntaxhighlight lang="Java" inline>Person</syntaxhighlight> automatisch auch die Methode <syntaxhighlight lang="Java" inline>talk</syntaxhighlight> weiterhin wie erwartet funktioniert.
}}
{{Inhaltsblock
|color=green
|vorher=Positivbeispiel:
|Beispiel=class Book {
[...]
@Override
public boolean equals(Object obj) {
// This will also do an implicit null-check so we don't have to worry about that here
return (obj instanceof this);
}
}
|beispielname=InstanceofGood
}}
}}

Aktuelle Version vom 15. Oktober 2025, 19:03 Uhr

🚧 Diese Seite befindet sich in Bearbeitung 🚧
🤓 Diese Seite ist eine Bewertungsrichtlinie, die ab Blatt 1 annotiert und ab Blatt 2 abgezogen wird. 🤓

Beschreibung

Die Java API bietet uns das Schlüsselwort instanceof, um zu prüfen, ob eine Objekt eine Instanz einer bestimmten Schnittstelle (Interface) oder Klasse ist.

In aller Regel kann die Verwendung von instanceof durch den Einsatz von Polymorphie umgangen werden, das heißt, man definiert eine Methode in der Oberklasse/im Interface, von dem alle betroffenen Klassen erben, die das gewünschte Verhalten umsetzt. Die Verwendung von instanceof gilt daher als äußerst schlechter Stil.

Im Rahmen dieses Übungsbetriebs ist die Verwendung von instanceof somit unzulässig.

Eine einzige Ausnahme besteht in der Implementierung der equals(Object o)-Methode einer Klasse. Üblicherweise prüft man in eigenen Implementierungen von equals zuallererst, ob das "andere" Objekt null ist, und wenn nicht, ob eine Instanz der entsprechenden Klasse ist. Diese beiden Prüfungen sind in einer instanceof-Abfrage möglich, wie im Positivbeispiel beschrieben. Zu diesem Zweck ist der Einsatz von instanceof erlaubt.

Negativbeispiel:

public void talk(Person[] persons) {
	for (Person person : persons) {
		if (person instanceof InfoStudent) {
			System.out.println("Ich studiere Informatik …");
		} else if (person instanceOf Employee) {
			System.out.println("Ich arbeite in der Industrie …");
		}
	}
}
Hier bestimmen instanceof-Abfragen das gewünschte Verhalten. Eine viel bessere Lösung wäre es hier, in der Klasse Person eine abstrakte Methode zu definieren, die einen String zurück- oder ausgibt. Diese Methode sollte dann von der Employee und InfoStudent Klasse geerbt und implementiert werden.

Positivbeispiel

abstract class Person {
	public abstract String getActivity();
}

class InfoStudent extens Person {
	@Override
	public String getActivity() {
		return "Ich studiere Informatik";
	}
}

class Employee extends Person {
	@Override
	public String getActivity() {
		return "Ich arbeite in der Industrie";
	}
}

//...
public void talk(Person[] persons) {
	for (Person person : persons) {
		System.out.printf("%s …%n", person.getActivity());
	}
}
Hier wird Vererbung genutzt um das gleiche Ergebnis zu erreichen wie oben. Durch die Verwendung von Vererbung wird das Projekt deutlich erweiterbarer, da beim Hinzufügen neuer Unterklassen von Person automatisch auch die Methode talk weiterhin wie erwartet funktioniert.

Positivbeispiel:

class Book {
	[...]
	@Override
	public boolean equals(Object obj) {
		// This will also do an implicit null-check so we don't have to worry about that here
		return (obj instanceof this);
	}
}