Inhaltsverzeichnis
Wie man Programme (ohne Mühe) um Methoden ergänzen kann
extends (Vererbung), import (importieren aus anderen Klassen), implements
import
Beispiele:
import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.Random;
usw.
Der import-Befehl ist sozusagen eine Pfad-Angabe, die dem Compiler ermöglicht, Methoden (oder Konstanten) aus den angegebenen Programmbibliotheken (packages) aufzurufen. Steht ein * im der Zeile, so bedeutet dass, das Zugriff auf alle dort abgelegten Methodenbibliotheken besteht - ohne * wird nur auf die angegebene Bibliothek zugegriffen.
Diese Methodenbibliotheken werden dabei nicht auf Vorrat in den Arbeitsspeicher geladen, sondern erst, wenn sie benötigt werden.
extends (Stichwort: Vererbung)
Beispiel:
public class Hund extends Tier
Es handelt sich hier um eine Verknüpfung zwischen zwei Klassen (Ober- und Unterklasse, IST-Beziehung). In der Unterklasse stehen alle (public/protected) Methoden und Instanzvariablen der Oberklasse zur Verfügung. Die Unterklasse kann durch weitere Methoden erweitert werden oder Methoden der Oberklasse überschreiben (gleiche Signatur).
Objekttyp | Name (oder Referenz) | Objekt und Referenz verknüpfen | Objekt wird erzeugt (durch Aufruf des Konstruktors der Klasse, hier: Hund) |
---|---|---|---|
Hund | meinHund | = | new Hund(); |
Tier | meinHund | = | new Hund(); |
//mein Hund wird aus Hund erzeugt, obwohl als Tier deklariert | |||
Deklaration | |||
Initialisierung |
Polymorphie
hier: Deklaration als Tier, erzeugt als Hund
Mit Polymorphie kann der Typ der Referenz eine Superklasse des tatsächlichen Objekttyps sein.
Anwendungsbeispiel: Tier-Array (z.B. die Liste einer Tierhandlung)
Tier[] tiere = new Tier[5];
tiere[0] = new Hund(); tiere[1] = new Katze(); tiere[2] = new Elefant(); tiere[3] = new Marsupilami(); tiere[4] = new Esel();
Wenn alle Tiere fressen sollen, lässt sich das jetzt einfach realisieren:
for(int i = 0; i < tiere.length; i++) tiere[i].fressen();
Die Methode fressen()
kann dabei entweder in den jeweiligen Sub-Klassen oder aber in der Super-Klasse implementiert sein.
Konkret vs. Abstrakt
Der Begriff „Tier“ ist jedoch abstrakter als der Begriff „Hund“. Die Eigenschaften eines Objekts vom Typ Hund sind also spezialisierter und spezifischer als die Eigenschaften eines Objekts vom Typ Tier.
In der Realität existieren nur konkrete Objekte - um das beim Programmieren zu berücksichtigen, sollte man die Klasse Tier „abstract“ anlegen, also nicht public class Tier
sondern
public abstract class Tier
oder
abstract public class Tier
Abstrakte Klassen geben Strukturen vor und können Oberklassen sein. Aus abstrakten Klassen lassen sich jedoch keine Objekte erzeugen.1)
Abstrakte Methoden enthalten keinen Rumpf, sondern nur die Signatur. Eine Klasse kann sowohl abstrakte als auch nicht-abstrakte (d.h. vollständig implementierte) Methoden enthalten - sobald aber mindestens eine abstrakte Methode vorhanden ist, muss die Klasse als abstrakte Klasse angelegt werden.
Im Tier-Beispiel sollen alle Tiere fressen können, also wird in der Klasse Tier eine Methoden fressen() als abstrakte Methode angelegt:
public abstract void fressen();
Spätestens jetzt muss die Klasse Tier als „abstract“ deklariert werden. Alle Unterklassen von Tier müssen dann die Methode überschreiben (implementieren):
public class Hund extends Tier { ... public void fressen() { irgendein Programmtext } }
Muss man überschreiben, will aber gar keinen Code implementieren, kann man den Methodenrumpf auch leer lassen:
public void fressen() { }
Besondere abstrakte Klassen - Interfaces
Ein Interface ist eine spezielle abstrakte Klasse, die nur abstrakte Methoden enthalten darf und dadurch das Erben von mehreren Klassen ermöglicht.
Bsp. (Grafik kommt noch)
public abstract class Tier {}
public class Katze extends Tier implements Haustier {}
public class Hund extends Tier implements Haustier {}
- extends: kann sich immer nur auf eine Oberklasse beziehen (Einfachvererbung)
- implements: kann den Zugriff auf eine Liste von Klassen ermöglichen (A, B, C …)
Da interface-Klassen nur abstrakte Methoden enthalten, kann es nie zu Konflikten beim Ausführen gleichnamiger Methoden kommen. Daher kann mit implements auf mehrere interface-Klassen zugegriffen werden. Sämtliche in den interface-Klassen deklarierte Methoden müssen jedoch in den Unterklassen implementiert werden (also mit einem Rumpf versehen, der jedoch auch leer sein kann).