Objektorientierte Programmierung OOP

KE3 Klassen, Objekte und Felder; Begriffe, Beispiele und Definitionen

KE3 Klassen, Objekte und Felder; Begriffe, Beispiele und Definitionen


S. H.
Diese Lernkarten bieten einen umfassenden Überblick über die Grundlagen der objektorientierten Programmierung (OOP) auf Universitätsniveau. Sie konzentrieren sich auf zentrale Konzepte wie Methoden, Objekte, Variablen und Klassen, wobei auch spezifische Themen wie Felder, Typen und Konstruktoren behandelt werden. Die Karteikarten eignen sich besonders für Studierende der Informatik, die ihr Verständnis von OOP vertiefen möchten, indem sie praktische Beispiele und Definitionen nutzen, um die theoretischen Grundlagen zu veranschaulichen.
Cartes-fiches
75
Utilisateurs
2
Langue
Allemand
Catégorie
Informatique
Niveau
Université
Créé / Mis à jour
23.02.2013 / 16.05.2022

Flashcards

Begriff: Was sind Objekttypen?

Objekttypen sind nicht von der Sprache Java vordefiniert, sondern durch Klassenvereinbarungen eingeführt werden.

Bemerkung: Kontext  

Damit eine Klasse verwendet werden kann, muss sie am Ort der Verwendung sichtbar sein. Solange keine ausdrücklichen Vorkehrungen zur Sichtbarkeit getroffen werden, umfasste der Kontext gewisse Klassen der Java-Laufzeitbibliothek (API) sowie diejenigen eigenen Klassen, die sich in demselben Verzeichnis wie die aufrufende Klasse befinden.

Rekapitulation: Was wissen wir berets über Objekte und Klassen?

• Objekte sind Exemplare1 einer Klasse.

• Objekte haben Attribute, auch Exemplarvariablen genannt.

• Attribute haben einen Typ und einen Attributwert.

• Der Zustand eines Objekts ist durch die Werte seiner Attribute festgelegt.

• Objekte haben Methoden, deren Ausführung durch das Senden einer Nachricht an das Objekt ausgelöst wird.

• Klassen beschreiben die Eigenschaften und das Verhalten aller ihrer Exemplare, denn durch die Klassenbeschreibung ist festgelegt, welche Attribute und Methoden Objekte dieser Klasse besitzen.

Beispiel: Wie kann ein einfacher Attributzugriff auf Objekte erfolgen?

In Java lassen sich die Attribute des Objekts rechnung1 wie folgt ansprechen [JLS: § 6.2, § 15.11]:

rechnung1.betrag

rechnung1.rabatt

Attributwerte lassen sich als Ausdrücke in Anweisungen auswerten:

System.out.println(rechnung1.betrag);

double nettopreis = rechnung1.betrag * (1 - rechnung1.rabatt);

Weiterhin können Attributen neue Werte zugewiesen werden:

rechnung1.betrag = 78.70;

rechnung1.rabatt = 0.0;

 

Bei der Auswertung wie bei der Zuweisung von Attributwerten gelten die Regeln der Typverträglichkeit.

Beispiel: Methodenaufruf

 

Wir erkennen, dass jede Methode einen Namen hat, der mit einem Klammerpaar endet. Über den Namen kann die Methode aufgerufen werden. Falls im Inneren des Klammerpaars ein oder mehrere Parameter angegeben sind, so bedeutet dies, dass die Methode bei ihrem Aufruf entsprechende Argumente benötigt. So muss beim Aufruf der Methode legeRabattFest() ein double-Wert an das Objekt übergeben werden. Die Anweisung  

rechnung1.legeRabattFest(0.05);  

bewirkt, dass die Methode legeRabattFest() des Rechnung-Objekts rechnung1 mit dem Parameter 0.05 ausgeführt wird. [JLS: § 6.2, § 15.12]

 

Bemerkung: Parameternamen  

Parameternamen, wie sie in der UML und auch in anderen Dokumentationsarten für Methoden oft angegeben werden, dienen dem Verständnis der Methode. Für den Methodenaufruf sind sie bedeutungslos.

Bemerkung: Welche Reihenfolge muss bei der Parameterübergabe in einer Methode eingehalten werden?  

Parameterreihenfolge Die Parameter müssen bei einem Methodenaufruf stets in der dokumentierten Reihenfolge übergeben werden.

Begriff: erläutern Sie die Begriffe Rückgabetyp:

Methoden können weiterhin ein Ergebnis zurückliefern, das außerhalb des Objekts weiter verwendet werden kann. Falls eine Methode ein Ergebnis zurückliefert, ist dies in einem UML-Klassendiagramm am Rückgabetyp zu erkennen, der hinter dem Klammerpaar und einem Doppelpunkt angegeben ist. Die Methode berechneNettopreis() liefert einen double-Wert an die aufrufende Stelle zurück, der beispielsweise in einer Zuweisung weiter verwendet werden kann:  

double nettopreis = rechnung1.berechneNettopreis();

  Für die Übergabe von Argumenten wie für die Auswertung von Rückgabewerten gelten die Regeln der Typverträglichkeit.

Bedeutung: Was bedeutet Lebensdauer und Objekterzeugung?

 

Im Unterschied zu Werten primitiver Datentypen haben Objekte eine Lebensdauer. Ein Objekt muss explizit erzeugt werden, bevor es einer Variablen zugewiesen werden kann. Nach seiner Erzeugung existiert ein Objekt solange, wie ein Verweis auf das Objekt existiert. Ein solcher Verweis ist beispielsweise eine andere Variable, der dasselbe Objekt zugewiesen ist. Ein Objekt, auf das kein Verweis mehr existiert, wird von Javas automatischer Speicherverwaltung (engl. garbage collection) aus dem Programmsystem entfernt.

Begriff: was führt der Kontruktor "new" aus?

Zur Erzeugung eines Objekts wird dem Konstruktor das Schlüsselwort new vorangestellt [JLS: § 15.9]. Ein Objekt vom Typ Rechnung können wir mit dem Ausdruck new Rechnung() erzeugen. Die Erzeugung wird in der Regel mit einer Zuweisung verbunden. Durch die Anweisung

Rechnung rechnung2 = new Rechnung();

wird eine Variable vom Typ Rechnung deklariert und dieser ein neu erzeugtes Rechnung-Objekt zugewiesen. Die Zuweisung kann auch an eine bereits zuvor deklarierte Variable erfolgen:

Rechnung rechnung3;

...

rechnung3 = new Rechnung();

Bedeutung: Welche zwei bedeutsamen Unterschiede zwischen Variablen für Objekttypen und Variablen für primitive Typen gibt es?

Zunächst kann eine Variable eines Objekttyps nur dann deklariert werden, wenn dieser Objekttyp im Kontext der Deklaration definiert ist. (Diese Einschränkung gilt verständlicherweise auch für die Erzeugung von Objekten.) Demgegenüber sind primitive Datentypen in Java global verfügbar, so dass Variablen - wie auch Literale - primitiver Datentypen an jeder Stelle eines Java-Programms auftreten können.

Bedeutung/Arbeitsweise: Wertvariabel von primitiven Datentypen.

Eine Variable ist eine benannte Speicherstelle im Arbeitsspeicher eines Rechners. Im Falle von primitiven Datentypen befindet sich an dieser Speicherstelle jeweils der Wert, der einer Variablen zugewiesen ist [JLS: § 4.12.1]. Abbildung zeigt schematisch die int-Variable laenge1 mit dem Wert 100.

Bedeutung/Arbeitsweise: Objektvariablen

Im Falle von Objekttypen befindet sich an der zugehörigen Speicherstelle nun aber nicht, wie man vielleicht vermuten könnte, das Objekt, das einer Variablen zugeReferenz wiesen ist, sondern lediglich eine Referenz auf einen anderen Speicherbereich, der das eigentliche Objekt beherbergt [JLS: § 4.12.2]. Die Abbildung zeigt schematisch die Variable rechnung1 vom Typ Rechnung. Das ihr zugewiesene RechnungObjekt befindet sich in einem anderen, von der virtuellen Maschine verwalteten Speicherbereich, auf dessen Adresse die Speicherstelle von rechnung1 verweist.

Beispiel: Wertvariable

Nehmen wir zwei Wertvariablen:

var1 = var2;

Eine solche Zuweisung bewirkt, dass der Inhalt der Speicherstelle von var2 in die Speicherstelle von var1 kopiert wird. Handelt es sich bei var1 und var2 um Variablen eines primitiven Datentyps (und somit um Wertvariablen), so wird der Wert von var2 in die Speicherstelle von var1 kopiert (Abbildung). 

Nach Ausführung der Anweisungsfolge

int laenge1 = 100;

int laenge2 = laenge1;

sind sowohl laenge1 als auch laenge2 mit dem Wert 100 belegt. (Die Zuweisung in der zweiten Zeile entspricht dem in Abb. 17.3-3 gezeigte Kopiervorgang.) Wie wir wissen, sind diese Werte zwar gleich, aber voneinander vollkommen unabhängig. So bewirkt die nachfolgende Anweisung

laenge2 += 300;

dass laenge2 den Wert 400 erhält, während laenge1 weiterhin mit dem Wert 100 belegt ist

Beispiel: Objektvariable

Handelt es sich bei var1 und var2 jedoch um Variablen eines Objekttyps (und somit um Verweisvariablen), so wird die Referenz auf ein Objekt in die Speicherstelle von var1 kopiert (Abbildung). Das Resultat des Kopiervorgangs sind somit zwei identische Referenzen, so dass rechnung1 und rechnung2 auf ein und dasselbe Rechnung-Objekt verweisen. Während die Wertvariablen laenge1 und laenge2 nach dem Kopiervorgang voneinander unabhängig geblieben sind, sind die Verweisvariablen durch den Kopiervorgang miteinander gekoppelt worden. Nach Ausführung der Anweisungsfolge

Rechnung rechnung1 = new Rechnung();

rechnung1.betrag = 100.0;

Rechnung rechnung2 = rechnung1;

rechnung2.betrag += 300.0;

ist sowohl rechnung1.betrag als auch rechnung2.betrag mit dem Wert 400.0 belegt, denn es handelt sich bei rechnung1.betrag und rechnung2.betrag um ein und dasselbe Attribut eines einzigen Objekts.

Arbeitsweise: Was passiert bei der Erzeugung neuer Referenzen auf ein Objekten? ziehe folgendes Beispiel:

Rechnung rechnung1 = new Rechnung();

rechnung1.betrag = 100.0;

Rechnung rechnung2 = rechnung1;

rechnung2.betrag += 300.0;

• new Rechnung() veranlasst die Erzeugung eines Rechnung-Objekts in einem von der virtuellen Maschine verwalteten Speicherbereich und liefert eine Referenz auf das Objekt. Eine Rechnung-Variable rechnung1 wird deklariert und erhält durch Zuweisung diese Referenz.

• Dem betrag-Attribut des von rechnung1 referenzierten Rechnung Objekts wird der Wert 100.0 zugewiesen.

• Eine weitere Rechnung-Variable rechnung2 wird deklariert und erhält durch Zuweisung eine Kopie der in rechnung1 gespeicherten Referenz. Die Zuweisung entspricht dem in der Abbildung gezeigte Kopiervorgang. Sie hat zur Folge, dass beide Variablen rechnung1 und rechnung2 auf dasselbe Rechnung-Objekt verweisen

 

• Der Wert des betrag-Attributs dieses nun von rechnung1 und rechnung2 referenzierten Rechnung-Objekts wird um 300.0 erhöht.

Aufgabe: Wie werden die referenzen auf zwei gleichen Objektvariablen gelöst? Wenn folgenes gilt:

Rechnung rechnung1 = new Rechnung();

Rechnung rechnung2 = Rechnung1;

rechnung2 = new Rechnung();

Aufgabe: Wie kann geprüft werden, wie zwei Verweisvariablen auf das gleiche Objekt zeigen?

rechnung1 == rechnung2    -> TRUE wenn sie die gleiche referenz haben.

rechnung1 != rechnung2   -> TRUE wenn die beiden Variablen eine unterschiedliche Referenzen besitzen.

Bemerkung: null Referenzen

Die Abbildung zeigt die Variable rechnung5 vom Typ Rechnung, die auf kein Objekt verweist. Das Schlüsselwort null können wir in Verbindung mit einem Gleichheits- oder Ungleichheitsoperator sowie in Zuweisungen verwenden. Der Ausdruck

rechnung5 == null

liefert true, falls rechnung5 auf kein Objekt verweist. Der Ausdruck

rechnung5 != null

liefert in demselben Fall entsprechend false. Wird ein referenziertes Objekt nicht mehr benötigt, so kann es durch

rechnung5 = null

von der referenzierenden Variablen gelöst werden. Falls es keine anderen Verweise auf dasselbe Objekt gibt, wird es in der Folge durch die automatische Speicherverwaltung entfernt.

Wie Variablen für primitive Datentypen können auch Variablen für Objekttypen mit dem Schlüsselwort final versehen werden:

final Rechnung RECHNUNG;

Nachdem der finalen Variablen RECHNUNG zum ersten Mal ein Rechnung-Objekt zugewiesen worden ist, kann keine erneute Zuweisung an diese Variable erfolgen. Beachten Sie jedoch, dass der Zustand des zugewiesenen Rechnung-Objekts weiterhin veränderlich ist.

Bemerkung: Attribute in UML-Klassendiagrammen  

Attribute primitiver Datentypen werden in der Attributliste einer Klasse aufgeführt. Ein Attribut eines Objekttyps kann entweder in der Attributliste aufgeführt oder durch eine Assoziation kenntlich gemacht werden. Die Darstellung durch eine Assoziation empfiehlt sich insbesondere bei der gleichzeitigen Darstellung des zugehörigen Objekttyps.

Aufgabe: Wo liegen die Unterschied von Klassen und Objekten?

Eine Klasse ist ein Vorbild, das beschreibt, wie ein Objekt auszusehen hat, wenn es erzeugt wird. Das Objekt ist ein Exemplar (engl. instance) der Klasse. Wir können uns eine Klasse einerseits als eine Fabrik vorstellen, die Objekte erzeugt, und auf der anderen Seite als Schablone, die die Eigenschaften und das Verhalten der Objekte beschreibt.

Definition: Klassenvereinbarung  

In der Regel hat eine Klassenvereinbarung die folgende Struktur:

class Klassenname {

    Attributdeklarationen

    Konstruktordeklarationen

    Methodendeklarationen }

Dabei sind die drei Bestandsteile im Inneren der Klasse optional. [JLS: § 8.1]  

Java-Konvention: Name von Klassen

Namen von Klassen sollten mit einem Großbuchstaben beginnen.

Aufgabe: Welchen unterschied hat ein Attribut zu einer Variable?

Ein Attribut ist eine speziele Variable, die die Eigenschaften von Klassen wieder gibt.

Begriff: Attributdeklaration

Eine Attributdeklaration hat die gleiche Form wie eine Attributdeklaration Variablendeklaration, sie besteht folglich aus dem Typen und dem Namen des Attributs [JLS: § 8.3].

class Rechnung {

// Attribute

double betrag = 0;

double mehrwertsteuer;

double rabatt; }

 

Java-Konvention: Attribusname

Für Attributsnamen gelten die gleichen Richtlinien wie für Variablennamen.

Bemerkung: Initialisierung von Attributen

Eine Attributdeklaration kann genauso wie eine Variablendeklaration eine Initialisierung beinhalten. Enthält eine Attributdeklaration keine Initialisierung und wird das Attribut vor seiner Benutzung nicht anderweitig initialisiert, so besitzt es einen Standardwert. Dieser ist bei allen numerischen Datentypen und Zeichen 0 Standardbelegung von bzw. 0.0 Attributen , bei boolean der Wert false und bei Verweisvariablen null. [JLS: § 8.3.2, § 4.12.5]

 

Bemerkung: Exemplarvariable  

Wir nennen Attribute auch Exemplarvariablen, da es sich in Java bei Attributen um Variablen handelt, die genau einmal pro Exemplar existieren. In der Literatur werden Sie auch oft den Begriff Instanzvariable finden.

Definition: Methodendeklaration  

Eine Methode hat einen Kopf und einen Rumpf. Die grundlegende Methodendeklaration hat folgende Form [JLS: § 8.4]:

ErgebnisTyp Methodenname(Parameterliste) {

    Anweisungen

}

Der Kopf in der ersten Zeile:

• zeigt uns, ob die Methode ein Ergebnis liefert und, wenn ja, von welchem Typ das Ergebnis ist: ErgebnisTyp ist entweder ein in diesem Kontext sichtbarer Typname oder das Schlüsselwort void, das angibt, dass kein Ergebnis bei der Methodenausführung geliefert wird,

• führt einen neuen Namen Methodenname ein und

• umfasst eine, möglicherweise leere Liste formaler Parameter (Parameterliste).

Eine Liste formaler Parameter hat die folgende Form:

t1 n1, ..., tm nm

wobei n1, ..., nm die paarweise verschiedenen Namen der formalen Parameter vom Typ t1, ..., tm sind.

Der Methodenrumpf umfasst eine Folge von Anweisungen, wie wir sie in der vor- Methodenrumpf angegangen Kurseinheit behandelten.

Beispiel: Methode in einer Klasse deklarieren

So können wir die Klasse Rechnung zum Beispiel um die Methode legeRabattFest(double neuerRabatt) ergänzen. Da die Methode kein Ergebnis erzeugt, ist sie als void deklariert.

class Rechnung {

    // Attribute

   double betrag = 0;

   double mehrwertsteuer;

   double rabatt;

   Kunde rechnungsempfaenger;

   // Methoden

   void legeRabattFest(double neuerRabatt) {

      // ...

   }

}

 

Definition: Signatur einer Methode  

Signatur einer Methode In Java besteht die Signatur einer Methode aus dem Methodennamen sowie den Typen ihrer formalen Parameter in der Reihenfolge der Vereinbarung. [JLS: § 8.4.2]

Begriff: überladener Methodenname

In einer Klasse darf es niemals mehrere Methoden mit der gleichen Signatur geben, sonst führt dies zu einem Übersetzungsfehler. Da die Signatur sich aber aus dem Methodennamen und den Parametertypen zusammensetzt, ist es möglich, dass mehrere Methoden mit dem gleichen Namen, aber mit verschiedenen Parametertypen existieren. Man spricht in diesem Fall von einem überladenen Methodennamen [JLS: § 8.4.9]. Bei einem Aufruf mit diesem Methodennamen wird an Hand der Typen der Argumente entschieden, welche der Methoden ausgeführt wird.

Begriff: lokale Variable

Diese Variablen nennen wir lokale Variablen, da sie nur in der Methode sichtbar sind [JLS: § 14.4, § 4.12.13].

Beispiel:

 

class Rechnung {    // Attribute    double betrag = 0.0;    double mehrwertsteuer;    double rabatt;    Kunde rechnungsempfaenger;    // Methoden    void gebeAus() {       // lokale Variablen       double netto = betrag * (1 - rabatt);       double brutto = netto * (1 + mehrwertsteuer);       System.out.println("An:");       System.out.println(rechnungsempfaenger.name);       System.out.println(rechnungsempfaenger.anschrift);       System.out.print("Netto: ");       System.out.println(netto);       System.out.print("MwSt: ");       System.out.println(mehrwertsteuer);       System.out.print("Brutto: ");       System.out.println(brutto);     } }

Bemerkung: Initialisierung von lokalen Variablen  

Alle lokalen Variablen müssen, anders als Attribute, vor ihrer ersten Verwendung explizit initialisiert werden.

Beispeil: Ändern von Attributen über einen Methoden aufruf.

In der Methode legeRabattFest(double neuerRabatt) muss der im Parameter neuerRabatt übergebene Wert im Attribut rabatt gespeichert werden, so dass dieser nach der Methodenausführung im Zustand des Rechnungsobjekts gespeichert ist. Wir können in Methoden nicht nur den Wert von Attributen auslesen, sondern diesen auch verändern. Da Parameter lokale Variablen sind, erfolgt der Zugriff auf die gleiche Weise. class Rechnung {

    // Attribute

   double betrag;

   double mehrwertsteuer;

   double rabatt;

   Kunde rechnungsempfaenger;

   // Methoden

   void legeRabattFest(double neuerRabatt) {

      rabatt = neuerRabatt;

   }

}

 

Java-Konventionen: Ändern von Parametern

Einem Parameter kann wie jeder anderen lokalen Variable auch ein neuer Wert zugewiesen werden, jedoch sollte dies wenn möglich vermieden werden. Um eine solche Zuweisung zu verhindern, kann ein Parameter als final deklariert werden, z. B. void legeRabattFest(final double neuerRabatt). Finale Parameter werden nicht mit Großbuchstaben geschrieben, da es sich nicht um Konstanten im eigentlichen Sinne handelt.

Begriff: this-Referenz

Innerhalb von Methoden kann es nützlich sein, einen Verweis auf ein Objekt zu haben, an dem die Methode gerade aufgerufen wurde. Diese Referenz erhält man mit Hilfe des Schlüsselworts this [JLS: § 15.8.3]. Der Typ der this-Referenz entspricht immer der umgebenden Klasse

Java-Konvention: Zugriff auf lokale Variablen und Attributte

Um eindeutig zwischen dem Zugriff auf eine lokale Variable und dem Zugriff auf ein Attribut zu unterscheiden, setzen wir vor jeden Attributzugriff das Schlüsselwort this. Dadurch wird beim Lesen direkt klar, ob es sich bei der verwendeten Variable um ein Attribut oder eine lokale Variable handelt. Zudem wird der Quelltext weniger fehleranfällig, wenn später Attribute oder lokale Variablen hinzugefügt, entfernt oder umbenannt werden. Die Methode legeRabattFest(final double neuerRabatt) würde dann folgendermaßen lauten:

class Rechnung {

    // Attribute double betrag;

   double mehrwertsteuer;

   double rabatt;

   Kunde rechnungsempfaenger;

   // Methoden

   void legeRabattFest(final double neuerRabatt) {        

      this.rabatt = neuerRabatt;

   }

}

Bemerkung: Verdeckung von Attributen  

Wenn in einer Methode eine lokale Variable den gleichen Namen wie ein Attribut trägt, so akzeptiert der Übersetzer dies, allerdings wird das Attribut innerhalb dieser Methode von der lokalen Variable verdeckt (engl. shadow) [JLS: § 14.4.3]. Steht bei einer Namensgleichheit von Attribut und lokaler Variable kein this vor dem Zugriff, so erfolgt der Zugriff auf die lokale Variable. Mit Hilfe von this kann immer auf das Attribut zugegriffen werden.

Definition: return- oder Rückgabeanweisung  

Eine return-Anweisung im Rumpf einer Methode dient zwei Zwecken:

• sie definiert einen Wert, dessen Typ verträglich sein muss mit dem Ergebnistyp der Methode in der sie vorkommt; dieser Wert ersetzt nach Ausführung der Methode den Methodenaufruf ;

• sie gibt die Kontrolle an die Aufrufstelle zurück.

Nach einer return-Anweisung (im Sinnen eines Ablaufpfads der Methode) dürfen keine weiteren Anweisungen vorkommen. Sie würden gemäß der Semantik der return-Anweisung nicht ausgeführt, und sie werden vom Java-Übersetzer auch nicht akzeptiert. Eine return-Anweisung hat die allgemeine Form:

return Ausdruck;

Wenn die return-Anweisung im Rumpf einer void-Methode benutzt wird, also einer Methode ohne Rückgabewert, darf kein Ausdruck in der return-Anweisung erscheinen. Andernfalls wird ein Übersetzerfehler auftreten. [JLS: § 14.17]

Étudier