» Tutorial / Java Grundlagen / objektorientierte Programmierung

Unser heutiges Kapitel wird die Grundlagen für die nächsten drei großen Teilbereiche schaffen. Hier wollen wir die wichtigsten Konzepte und ein allgemeines Verständnis für die objektorientierte Programmierung schaffen. Auf diese werden wir später praktisch eingehen und sie in kleinen Testprogrammen praktisch anwenden.


» grundlegende Konzepte nach oben «

So bedeutend die objektorientierte Programmierung auch sein kann, so verwirrend kann sie auch erscheinen. Daher wollen wir uns hier ihre Merkmale vor Augen führen und einen Blick hinter die Kulissen der Programmierer werfen, die diese Konzepte erfolgreich umsetzen.

Der Schlüssel dafür liegt im allgemeinen Verständnis der Vorgänge und dem Sinn dahinter. Hat man diese einmal verinnerlicht, so fällt auch die spätere praktische Umsetzung um einiges leichter.


» Abstraktion

Bei der Abstraktion wird stets zwischen dem Konzept und einem konkreten Objekt unterschieden. Das Konzept beschreibt praktisch den Bauplan eines Objekts in all seinen Details. Erst die Erzeugung eines Objekts auf der Basis dieser Definition erlaubt allerdings das Arbeiten mit den Informationen.

Der Programmierer instanziiert sein Objekt und kann gemäß der Spezifikation des Konzepts mit diesem arbeiten. Das heißt, das dem Programmierer nur eine feste Schnittstelle vorgegeben wird, anhand derer er mit dem Objekt interagieren kann.

Die Details der Implementierung sind ihm dabei vollkommen unbekannt. Er benötigt lediglich Angaben über die zur Verfügung stehenden Methoden und etwaiger Datenelemente der Klasse.

Das Konzept der Abstraktion trennt also Implementierung und Verwendung. Dieses Konzept erlaubt es des weiteren, die Datails zu ignorieren und selbst komplexe Probleme lösen zu können.

» Kapselung

Das Konzept der Kapselung beschreibt die Zusammenfassung von Variablen (Eigenschaften eines Objekts) und Methoden (Verhalten eines Objekts) zu einer Einheit, in Java in Form einer sogenannten Klasse. Diese kann man sich als eine Art Container für Variablen aller Art und Methoden vorstellen. Diese Klasse nutzt eben diese Elemente, um eine feste Aufgabe zu lösen.

Des weiteren gelten diese Daten als in der Klasse abgeschlossen. Alle Details der Implementierung sollen der Außenwelt vorenthalten werden, lediglich eine feste Schnittstelle aus Methoden soll die Interaktion ermöglichen. Auch der Bereich des Schutzes von Informationen und Details zählt also zum Thema der Kapselung.

Prinzip der Datenkapselung

Gleichzeitig wird eine Art Sicherheitsfunktion mit eingebaut, denn durch die konsequente Nutzung von Methoden wird ein kontrollierter und sicherer Datenaustausch gewährleistet, der durch entsprechende Tests in den Methoden Fehler bereits frühzeitig erkennt und korrigiert.

» Wiederverwendbarkeit

Die Abstraktion und Kapselung ermöglichen eine konsequente Wiederverwendbarkeit von Programmteilen. Durch die Tatsache, dass alle Objekte durch einen festen Bauplan bestimmt werden, ist es möglich, auch mehrere Instanzen einer Klasse zu erzeugen und diese sind dann auf die gleiche Art und Weise zu nutzen wie Klassen des gleichen Typs.

Ist die Klasse dazu noch vollständig autark und bedarf keiner anderen Klassen, um ihre Funktion zu erfüllen, so wird die Wiederverwendbarkeit noch gefördert.

Nutzen der Wiederverwendbarkeit

» Generalisierung und Spezialisierung

Dieses Konzept konzentriert sich bereits stark auf die Vererbungsmechanismen, weshalb wir hier etwas vorgreifen möchten. Java bietet die Möglichkeit, eine komplette Vererbungshierarchie zwischen Klassen nachzubilden. Leitet man also eine Klasse von einer anderen ab, so erbt die neue Klasse alle Elemente und Fähigkeiten ihrer Vaterklasse. Diese können wiederum in der neuen Klasse ergänzt und erweitert werden.

Erweitert eine abgeleitete Klasse die Fähigkeiten und Elemente ihrer Vaterklasse, so spricht man auch von der Spezialisierung, da die neue Klasse dem nachgebildeten Realitätsmodell bereits weitaus näher ist. Der umgekehrte Weg von der abgeleiteten Klasse zur Basisklasse hingegen wird als Generalisierung bezeichnet, da dass gesamte nachgebildete Modell nach oben hin verallgemeinert wird.

Generalisierung und Spezialisierung

» Aggregation und Komposition

Die Aggregation beschreibt den Fall, in dem ein Objekt andere Objekte aufnehmen und verwalten kann. Bei diesem Prinzip ist das als Container fungierende Objekt nicht von den aufnehmbaren Objekten abhängig. Anders bei der Komposition. Sie beschreibt die Zusammensetzung eines Objekts aus anderen Objekten, welche neue Funktionalitäten hinzufügen oder für die Erfüllung einer Aufgabe unerlässlich sind.

Beide Fälle spielen in der objektorientierten Programmierung eine wichtige Rolle und werden demnach streng unterschieden, auch wenn die Umsetzungen dieser Konzepte letztlich die Gleichen sind.

Aggregation und Komposition

» Beziehungen

An dieser Stelle sollen uns noch die möglichen Beziehungen zwischen den Klassen und Objekten interessieren. Auch wenn wir sie nur im Ansatz erwähnt haben, so lernten wir bereits zwei Beziehungen kennen.

Beziehung
 
is a
part of

Bei der Spezialisierung ist jede abgeleitete Klasse prinzipiell typverwandt mit ihrer Basisklasse, denn beide haben die gleichen Grundelemente. Daher sagt man auch, die Subklasse ist eine typverwandte Klasse der Superklasse.

Ähnliches gilt für die Aggregation und Spezialisierung, nur dass hier die Objekte aufgenommen werden. Man sagt, die aufgenommenen Objekte sind Teil der Superklasse.

Die dritte und neu angesprochene Beziehung ist die Aufruf- und Verwendungsbeziehung zwischen Objekten. Diese schlägt sich im Informationsaustausch der Objekte untereinander nieder, der in der Regel über den Aufruf von Methoden stattfindet. So kommunizieren alle Objekte miteinander und lassen gegenseitig diverse Operationen ausführen, beziehungsweise bedienen sich der Funktionalität und Daten von externen Objekten.

Kommunikationsprinzip unter den Objekten

» Polymorphismus

Übersetzt bedeutet es Vielgestaltigkeit und beschreibt die Fähigkeit, Objekte aufzunehmen, welche sich in der gleichen Vererbungshierarchie befinden.

Alle Subklassen enthalten die gleichen Elemente wie ihre Basisklassen, können diese allerdings noch erweitern. Dennoch sind sie vom Typ her ihrer Basisklasse zuweisbar. Dadurch ist es einer Basisklasse auch möglich, auf einen Typ einer untergeordneten Klasse zu verweisen. Dabei stellt exakt diese Basisklassen aber auch nur die Elemente der Subklasse zur Verfügung, die auch sie enthält, denn von neue definierten Elementen weis sie ja nichts.

Der umgekehrte Weg kann allerdings nicht gegangen werden, da ein Verweis von einer Subklasse auf eine Basisklasse nicht die gleichen Grundeigenschaften besitzen würde, denn diesmal stellt die Subklasse mit wesentlich mehr Elementen die Basis dar. Polymorphismus ist also nur in eine Richtung möglich, dies reicht allerdings auch aus.

Dieses Konzept wird uns verstärkt in der praktischen Anwendung in den folgenden beiden Kapiteln beschäftigen. Dort werden wir den großen Nutzen dieses Systems kennenlernen.


» Klassen und Objekte nach oben «

An dieser Stelle möchten wir die Unterschiede zwischen den Bezeichnungen einer Klasse und eines Objekts aufgreifen. Wie bereits erwähnt, so stellt eine Klasse nur den formalen Bauplan eines Objekts dar, indem sie es in allen Einzelheiten beschreibt. Auch die Programmierung aller internen Routinen enthält diese Definition bereits. Erst von dieser Klasse werden dann konkrete Objekte instanziiert und auf dem Speicher angelegt. Dies ermöglicht dann auch das Arbeiten mit dem Objekt, wenn zum Beispiel Werte verwaltet und manipuliert werden sollen.

Instanziierung von Objekten


» Inhalte von Klassen nach oben «

Klassen können nahezu alle Sprachelemente der Java - Sprachspezifikation aufnehmen. Wichtig ist dabei vorallem die Aufnahme von Datenelementen, Methoden und Konstruktoren, die die Funktionalität der Klasse nachbilden und implementieren. Aber auch andere Klassen können wiederum als Elemente verwendet werden. Die interne Programmierung der Klasse nutzt alle bis jetzt bekannten Sprachelemente wie Schleifen, Bedinungen, Operatoren uns so weiter. Ihnen sind also alle Möglichkeiten der Programmierung eigener Klassen offen gehalten.


» Planung eigener Klassen nach oben «

Jeder kommt bereits bei der Programmierung recht simpler Anwendungen unmittelbar in die Lage, eigene Klassen programmieren zu müssen, um das gewünschte Ziel realisieren zu können. Hier ist es hilfreich, sich zunächst einige wichtige Fragen zur Klasse zu stellen, die helfen, das Problem einzugrenzen und möglichst umfangreich zu behandeln. Ziel ist es, eine Klasse zu schreiben, die leicht zu verwenden, übersichtlich und frei von unnützen Ballast ist.

Um die Aufgabe so gut wie möglich zu lösen, stellen wir uns folgende grundlegende Fragen.

Auch Details der Umgebung der Klasse im weiteren Rahmen können bereits interessant sein, um möglichst frühzeitig Schwerpunkte im Klassendesign setzen zu können.

In der Regel reichen diese Schwerpunkte schon aus, um die Klasse weitestgehenst zu planen und zu implementieren.

» Welche Fähigkeiten hat das Objekt?

Unter dieser Fragestellung werden alle etwaigen Aufgaben der Klasse gesammelt. Um diese später ausführen zu können, werden diese in Methoden verpackt. Diese nutzen dann gegebenenfalls interne Daten um eine Lösung zu erhalten. Die Methoden werden in der Regel mit Verben benannt, die ihre Funktionalität bereits im Namen unterstreichen.

» Welche Eigenschaften hat das Objekt?

Eigenschaften eines Objekts werden durch Variablen verschiedenster Art repräsentiert. Sie speichern wichtige Informationen, mit denen die Methoden der Klasse dann operieren. Jeder Datentyp, sei es primitiver oder benutzerdefinierter, ist möglich. Auch Arrays, Strings und andere Objekte können in der Klasse als Informationsträger fungieren.

» Welche Initialisierungen müssen vorgenommen werden?

Dieser Aspekt wird in der Regel dann betrachtet, wenn alle benötigten Variablen und Methoden feststehen. Ein Objekt wird durch eine spezielle Art von Methode, dem Konstruktor, auf dem Speicher instanziiert. Dabei hat der Programmierer die Möglichkeit, allen Variablen des Objekts spezielle Startwerte zuzuweisen, um ein sicheres Arbeiten zu ermöglichen. Eine Klasse kann außerdem mehrere Konstruktoren für die unterschiedlichsten Gelegenheiten definieren.

» Welche Daten sollen dem Benutzer zugänglich sein?

Hier betrachten wir zum ersten mal das Sicherheitskonzept einer Klasse. Alle Variablen und Methoden einer Klasse lassen sich in verschiedene Sektoren der Klasse einteilen. Sowohl in öffentliche, sprich dem Benutzer zugängliche, als auch private Sektoren, auf die von Außen kein Zugriff möglich ist. Da die Variablen in der Regel sensible Daten speichern, werden diese meist als nicht zugänglich eingeordnet. Lediglich durch öffentliche Methoden wird das Setzen und Lesen von Variablen ermöglicht und kontrolliert. Daher ist anzuraten, dieses Konzept konsequent anzuwenden.

» Ist das Objekt Teil einer Vererbungshierarchie?

Wenn Sie komplexe Strukturen nahe der Realität nachbilden möchten, so stellt sich des öfteren die Frage, ob verschiedene Klassen Teil einer gemeinsamen Hierarchie sind. In diesem Fall lassen sich zunächst abstrakte Klassen erstellen, die lediglich grundlegende Eigenschaften und Fähigkeiten aller folgenden Klassen definieren. Durch diese logische Aufteilung lassen sich komplexe Gebilde leicht kontrollieren und erweitern. Daher sollten bereits frühzeitig entsprechende Überlegungen gemacht werden. Entsprechende Beispiele zum Thema folgen im Kapitel elf, wo dieses Thema ausgiebig behandelt wird.

» Ist das Objekt von anderen Klassen abhängig?

Wenn man selbst das Rad nicht jedesmal neu erfinden möchte, so bildet die Java - Bibliothek einen idealen Fundort für wiederverwendbare Klassen. Deren Funktionalitäten können Sie ihrem Projekt hinzufügen. Aber auch selbst definierte Klassen können untereinander verwendet werden, sei es, um komplexe Aufgaben weiter auf kleinere Objekte aufzuteilen. Hier muss die entsprechende Syntax und Strukturierung der Fremdobjekte beachtet werden, damit diese korrekt implementiert und genutzt werden können.


» Vererbung nach oben «

Unter Vererbung versteht man die Übertragung von Eigenschaften einer Klasse auf eine andere. Dabei kann eine abgeleitete Klasse sowohl von einer Klasse erben (Einfachvererbung), als auch von mehreren (Mehrfachvererbung). Java selbst kennt im Klassenkonzept nur die Einfachvererbung, um den Problemen der Mehrfachvererbung aus anderen Programmiersprachen aus dem Weg zu gehen.

Um dennoch den Ansatz einer multiplen Vererbungshierarchie in Form der Mehrfachvererbung zu realisieren, hat man das Sprachkonstrukt der Interfaces hinzugefügt, das in einem gewissen Rahmen die Mehrfachvererbung durchsetzt.

Vererbungshierarchie zwischen Klassen

Wie zu erkennen ist, so können durchaus mehrere Klassen von einer Basisklasse abgeleitet werden. Auch wenn nun wiederum Klassen von den Subklassen abgeleitet werden, so sind diese immernoch indirekt von der obersten Basisklasse bestimmt. In der Grafik taucht die Bezeichnung der spezifischen Vererbung auf. Damit ist gemeint, dass nicht zwangsläufig alle Elemente einer Klasse konsequent auf die Subklassen übertragen werden. Dieses Verhalten lässt sich weitestgehend vom Programmierer selbst bestimmen. Mehr dazu im entsprechenden Kapitel.

Nun haben wir aber auch den Fall der Mehrfachvererbung angesprochen, worauf wir hier etwas vorarbeiten möchten. In der Tat ist es so, dass eine Subklasse nur eine Superklasse haben kann. Möchte man nun aber die Funktionalitäten mehrerer Klassen in einer neuen vereinen, so ist dies nicht direkt möglich.

In diesem Fall wurde das Konzept der Interfaces eingeführt. Diese Schnittstellen definieren lediglich leere Methoden und sollen vorschreiben, welche Funktionalitäten eine von ihr abgeleiteten Klasse zu implementieren hat. Klassen sind nun in der Lage, mehrere dieser Schnittstellen aufzunehmen und deren Methoden zu überschreiben.

Vererbungshierarchie mit Interfaces


» globale Superklasse nach oben «

Java ist ein Meisterwerk der objektorientierten Programmierung, was sich spätestens in den Studien der Java - Bibliotheken zeigt. Alle Klassen von Java gehen auf ein globales Objekt zurück und selbst benutzerdefiierte Klassen nutzen dessen Methoden und Eigenschaften. Die Rede ist von der Klasse Object. Selbst wenn man eigene Klassen erstellt, die nicht Teil einer Vererbungshierarchie sind, so werden diese von Java implizit von Object abgeleitet.

globale Superklasse

Die Methoden dieser Klasse sind auf alle Objekte anwendbar. Eine entsprechende Auflistung aller Elemente dieser Klasse finden Sie in unserer Referenz zu den Klassen der Java - Bibliothek.


« Kapitel Kapitelübersicht nach oben Kapitel »