Polymorphie: Unterschied zwischen den Versionen

Aus Programmieren-Wiki
Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
Zeile 10: Zeile 10:


<syntaxhighlight lang="Java">
<syntaxhighlight lang="Java">
class Animal {
abstract class Animal {
void breathe();
void breathe() { /* [...] */ }
abstract void speak();
abstract void speak();
}
}
Zeile 21: Zeile 21:
}
}
public void purr() {}
public void purr() { /* [...] */ }
}
}


Zeile 30: Zeile 30:
}
}


public void fetch() {}
public void fetch() { /* [...] */ }
}
}
</syntaxhighlight>
</syntaxhighlight>
Zeile 79: Zeile 79:
Auch wenn das auf den ersten Blick "leicht" zu erweitern wäre und die gewollte Funktionalität implementiert, ist es viel komplizierter und fehleranfälliger als es eigentlich sein müsste.
Auch wenn das auf den ersten Blick "leicht" zu erweitern wäre und die gewollte Funktionalität implementiert, ist es viel komplizierter und fehleranfälliger als es eigentlich sein müsste.
|positiv=<syntaxhighlight lang="Java">
|positiv=<syntaxhighlight lang="Java">
class Animal {
abstract class Animal {
abstract void speak() {};
abstract void speak() {};
}
}

Version vom 2. Mai 2025, 17:18 Uhr

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

Beschreibung

Wenn wir von Polymorphie reden, sprechen wir vor allem von Vererbung von Klassen und Methoden. Also einem Kernbestandteil der Objektorientierten Programmierung.

Durch das Vererben von Eigenschaften an sogenannte "Kindklassen" verringern wir den Anteil an Code, den wir sonst mehrfach kopieren müssten. Auch ermöglicht dieses Vorgehen uns, verschiedene Eigenschaften von sonst ähnlichen Objekten schnell und unabhängig zu modellieren.

Gerne wird bei Polymorphie in der Objektorientierten Programmierung auf die Polymorphie in der Biologie verwiesen, da diese einem ähnlichem, wenn nicht sogar sehr gleichem Konzept folgt. Wir geben ein klassisches Beispiel:

abstract class Animal {
	void breathe() { /* [...] */ }
	abstract void speak();
}

class Cat extends Animal {
	@Override
	public void speak() {
		System.out.println("Meow");
	}
	
	public void purr() { /* [...] */ }
}

class Dog extends Animal {
	@Override
	public void speak() {
		System.out.println("Bark");
	}

	public void fetch() { /* [...] */ }
}

Schreiben wir die Klassen einmal in ein biologisches Äquivalent um:

Katzen und Hunde sind beides Tiere, teilen also schon einmal diese Eigenschaft. Auch können alle Tiere kommunizieren und atmen. Hunde und Katzen kommunizieren dabei aber unterschiedlich. Was Hunde und Katzen beide (in unserem Beispiel jetzt) nicht teilen, ist, dass Hunde gerne Bälle und Stöcke zurückbringen und Katzen schnurren.

Die Polymorphie entsteht also dadurch, dass wir verschiedene Tiere (Childclasses) mit jedoch auch gleichen Eigenschaften haben und diese mit einem Überbegriff (Parentclasses) darstellen können.

Warum den ganzen Aufwand? Wir können ja einfach die Klasse prüfen und entsprechend reagieren ... oder?

Schauen wir uns das mal in einem konkreten, überzugenden Beispiel an:


Negativbeispiel

class Cat{
	public void speak() {}

	public void purr() {}
}

class Dog{
	public void speak() {}

	public void fetch() {}
}

class Main {
	public static void main(String[] args) {
		Dog dog = new Dog();
                speak(dog);
                Cat cat = new Cat();
                speak(cat);
	}

	public void speak(T animal) {
		if (animal instanceOf Cat) {
			System.out.println("Cat has spoken");	
		} else if (animal instanceOf Dog) {
			System.out.println("Dog has spoken");
		} else {
			System.out.println("I don't know how that animal speaks");
		}
	} 
}

Auch wenn das auf den ersten Blick "leicht" zu erweitern wäre und die gewollte Funktionalität implementiert, ist es viel komplizierter und fehleranfälliger als es eigentlich sein müsste.

Positivbeispiel

abstract class Animal {
	abstract void speak() {};
}

class Cat extends Animal {
	@Override
	public void speak() {}
	
	public void purr() {}
}

class Dog extends Animal {
	@Override
	public void speak() {}
	
	public void fetch() {}
}

class Main {
	public static void main(String[] args) {
		Animal[] animals = {new Dog(), new Cat()};
		for (Animal animal : animals) {
			animal.speak();
		}
	}
}

animal.speak() kann hier keinen Fehler erzeugen, da die Methode in allen Klassen entsprechend definiert ist.