Objektorientierte Programmierung
Ziele
- Ich kann ohne Hilfsmittel die Bestandteile einer Klasse vollständig auflisten.
- Ich kann den Unterschied zwischen einer Klasse und einem Objekt mit konkreten Beispielen demonstrieren.
- Ich implementiere Klassen anhand vorgegebenen Anforderungen und instanziiere (erzeuge) Objekte dazu.
Einführung
In der realen Welt können wir viele Objekte wie Autos, Gebäude und Menschen um uns herum finden. Alle diese Objekte haben einen bestimmten Zustand/Merkmale und ein bestimmtes Verhalten.
Wenn wir ein Auto betrachten, so könnte sein Zustand/seine Merkmale
- einen Markennamen,
- eine bestimmte Geschwindigkeit
- oder den zu tankenden Kraftstoff enthalten.
Mögliche Verhaltensweisen eines Autos sind normalerweise
- fahren
- und einparken.
Problemstellung
Stell dir vor, du möchtest ein Auto in Java programmieren. Dazu könnten wir für jedes Auto einfach drei separate Variablen verwenden:
|
|
Das funktioniert für ein oder zwei Autos, aber was passiert, wenn wir viele Autos haben? Was passiert, wenn wir viele Autos haben? Es wird schwierig, jedes Auto mit seinen individuellen Merkmalen zu verwalten, und der Code wird unübersichtlich. Wir müssten mehrere Variablen für jeden Zustand eines Autos pflegen. Eine Lösung wäre die Verwendung von Arrays:
|
|
Probleme mit dieser Lösung:
- Wir müssen immer sicherstellen, dass die Daten für jedes Auto an der gleichen Position in allen Arrays stehen. Das erhöht die Komplexität.
- Es ist schwer, weitere Funktionen für jedes Auto hinzuzufügen oder das Verhalten zu modellieren.
Wäre es nicht cool, wenn wir diese Eigenschaften zusammenfassen könnten? Eine bessere Lösung besteht darin, eine Klasse zu erstellen, die alle Merkmale eines Autos beschreibt. Dadurch können wir sowohl den Zustand als auch das Verhalten eines Autos kapseln.
|
|
Nun können wir Objekte dieser Klasse erstellen. Ein Objekt hat diese Eigenschaften zur Verfügung und kann sie entsprechend setzen:
|
|
Vorteile dieser Lösung:
- Die Eigenschaften eines Autos sind in einer einzigen Einheit (Klasse) zusammengefasst.
- Es ist einfach, neue Autos zu erstellen und zu verwalten, da wir nicht mehr mehrere Arrays benötigen. Wir können einfach einen Array von unserem Typ Auto erstellen:
Auto[] autos
. - Der Code wird klarer und wartbarer.
Klassen können noch viel mehr als nur Behälter für mehrere Variablen sein. Das wirst du in den folgenden Kapiteln lernen.
Definitionen
Um die nachfolgenden Kapitel besser zu verstehen, ist es hilfreich zuerst einige Basisdefinitionen zu etablieren.
Objektorientierte Programmierung
Das Konzept der objektorientierten Programmierung soll helfen eine Struktur in eine Anwendung zu bringen. Das Ziel ist es, Daten und Methoden, die zusammengehören, in einer Klasse zusammenzufassen. Dies führt auch dazu, dass der Code wiederverwendbarer wird, da einfach neue Instanzen/Objekte dieser Klasse erstellt werden können.
Klasse
Eine Klasse ist eine Vorlage, die die gemeinsamen Eigenschaften und das Verhalten von Objekten desselben Typs beschreibt Die Klasse dient als Bauplan für die Abbildung von realen Objekten in Softwareobjekte und beschreibt Attribute (Eigenschaften) und Methoden ( Verhaltensweisen) der Objekte.
Objekt
Ein Objekt bezeichnet in der objektorientierten Programmierung ein Exemplar eines bestimmten Datentyps oder einer bestimmter Klasse. Objekte sind konkrete Ausprägungen (=Instanzen) einer Klasse und werden zur Laufzeit erzeugt (Instanziierung).
Datenfelder
Datenfelder (Attribute) enthalten Informationen, die für Objekte dieser Klasse relevant sind.
Beispielsweise hat ein Auto eine Höchstgeschwindigkeit, eine bestimmte Anzahl von Sitzen, usw. Das
heisst, ein Feld ist eine Variable, in der Daten gespeichert werden können. Es kann einen beliebigen
Typ haben, einschliesslich primitiver Typen (int
, float
, boolean
usw.) und Klassen. Eine
Klasse kann auch sich selber als Feld enthalten. Eine Klasse kann beliebig viele Felder haben.
Methoden
Methoden dienen dazu, den Zustand eines Objekts zu verändern. Die Methode refuel()
(siehe
Klassendiagramm unten) füllt beispielsweise den Tank, bis dessen Kapazität erreicht wird.
Zusammenfassung
Klassen werden verwendet, um benutzerdefinierte Datentypen darzustellen. Damit werden Attribute und Verhalten, welche zu diesem neuen Datentyp gehören, an einer Stelle im Code zusammengefasst und verwaltet. Diese neuen, benutzerdefinierte Datentypen können dann wie anderen Datentypen (primitive Datentypen oder andere Klassen) verwendet werden.
Beginnen wir mit einem Beispiel einer Auto-Klasse; hier siehst du das UML-Klassendiagramm der
Klasse Car
, die wir selber erfunden haben. Die oberen 4 Einträge sind ihre Instanzvariablen und
die untersten 3 sind ihre Methoden. Einträge mit einem -
sind private
, Einträge mit einem +
sind öffentlich (public
):
class Car |
---|
- topSpeed: int |
- totalSeats: int |
- fuelCapacity: int |
- manufacturer: String |
+ refuel(): void |
+ park(): void |
+ drive(): void |
Klassen und Objekte im Schnelldurchlauf
Klassen deklarieren
Eine Java Klasse besteht aus zwei Teilen: Dem Klassenkopf und dem Klassenrumpf.
Im Klassenkopf (auch Klassendeklaration genannt) wird eine neue Klasse mit dem Keyword class
gefolgt vom Namen der Klasse deklariert. Per Konvention folgt die Benamsung der Klasse dem
PascalCase. Das bedeutet, dass der Klassen-Name und jedes neue Wort darin mit einem Grossbuchstaben
beginnt, der Rest besteht aus Kleinbuchstaben.
Wie folgt kannst du eine Klasse mit dem Namen Nothing erstellen:
|
|
Der “Klassenrumpf” besteht aus einer öffnender {
und schliessenden geschweiften Klammer }
. Diese
Klammern bilden die Grenzen der Klasse. Der Klassenrumpf kann Felder, Methoden und Konstruktoren
enthalten. Felder speichern Daten, Methoden definieren das Verhalten und Konstruktoren ermöglichen
es uns, neue Objekte der Klasse zu erstellen und zu initialisieren. Felder und Methoden gelten als
Klassenmitglieder (class members).
Der Quellcode einer Klasse wird in eine .java-Datei eingefügt. Normalerweise enthält eine Quellcodedatei nur eine Klasse und hat denselben Namen wie diese Klasse. Manchmal kann eine Datei jedoch auch mehrere Klassen enthalten, jedoch darf es nur eine öffentliche (public) Klasse pro Datei geben. Deren Name muss mit dem Dateinamen übereinstimmen.
Nachfolgend die Klasse Patient
in der Datei Patient.java
:
|
|
Diese Klasse repräsentiert einen Patienten in einem Krankenhausinformationssystem. Sie verfügt über
vier Felder: name
, age
, size
und complaints
. Alle Objekte der Klasse Patient haben dieselben
Felder, aber ihre Werte können für jedes Objekt unterschiedlich sein.
Objekte erstellen
Patient.java
|
|
Wir können ein Objekt (auch “eine Instanz” genannt) der Klasse Patient
mit dem Operator new
erstellen:
|
|
Wenn du ein neues Objekt erstellst, wird jedes Feld mit dem Standardwert des entsprechenden Typs
initialisiert (insofern du keinen Konstruktor mit Argumenten verwendest, dazu aber später mehr).
Wenn die Instanzvariablen eines Objektes nicht mit einem Zugriffsmodifikator wie private
versehen
sind (dazu unten mehr), können wir mittels Punkt-Operator auf die Variablen des Objekts zugreifen:
|
|
Das folgende Programm erstellt zwei Objekte der Klasse Patient und druckt die Informationen der Objekte aus.
PatientDemo.java
|
|
Im obigen Code haben wir zwei Patienten erstellt, John und Alice, die Werte ihrer Felder definiert und dann die Informationen über sie ausgedruckt. Wir sehen, dass wir mit dem Punkt-Operator auf die Felder des Objekts zugreifen können (john.name = “John”). Allerdings soll hier erwähnt sein, dass das nur geht, wenn die Instanzvariablen nicht private sind (wir behandeln das Thema Zugriffsmodifikatoren später).
Referenzen teilen
Objekte sind Referenztypen. In einer Variable wird also nicht das Objekt selbst, sondern die Speicheradresse hinterlegt, welche auf das Objekt zeigt. Es können sich also mehrere Referenzen auf dasselbe Objekt beziehen.
|
|
Es ist wichtig zu verstehen, dass sich die zwei Referenzen oben auf das gleiche Objekt im Speicher beziehen und nicht auf zwei unabhängige Kopien. Da unsere Klasse veränderbar ist, können wir das Objekt mit Hilfe beider Referenzen ändern.
|
|