Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.
 
Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Eigene Klassen schreiben
6 Objektorientierte Beziehungsfragen
7 Ausnahmen müssen sein
8 Äußere.innere Klassen
9 Besondere Typen der Java SE
10 Generics<T>
11 Lambda-Ausdrücke und funktionale Programmierung
12 Architektur, Design und angewandte Objektorientierung
13 Die Klassenbibliothek
14 Einführung in die nebenläufige Programmierung
15 Einführung in Datenstrukturen und Algorithmen
16 Einführung in grafische Oberflächen
17 Einführung in Dateien und Datenströme
18 Einführung ins Datenbankmanagement mit JDBC
19 Einführung in <XML>
20 Testen mit JUnit
21 Bits und Bytes und Mathematisches
22 Die Werkzeuge des JDK
A Java SE Paketübersicht
Stichwortverzeichnis

Download:
- Beispielprogramme, ca. 20,0 MB
- Übungsaufgaben, ca. 1,8 MB
- Musterlösungen, ca. 0,8 MB

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenbloom
Das umfassende Handbuch
Buch: Java ist auch eine Insel

Java ist auch eine Insel
Rheinwerk Computing
1306 Seiten, gebunden, 11. Auflage
49,90 Euro, ISBN 978-3-8362-2873-2
Pfeil 6 Objektorientierte Beziehungsfragen
Pfeil 6.1 Assoziationen zwischen Objekten
Pfeil 6.1.1 Unidirektionale 1:1-Beziehung
Pfeil 6.1.2 Zwei Freunde müsst ihr werden – bidirektionale 1:1-Beziehungen
Pfeil 6.1.3 Unidirektionale 1:n-Beziehung
Pfeil 6.2 Vererbung
Pfeil 6.2.1 Vererbung in Java
Pfeil 6.2.2 Spielobjekte modellieren
Pfeil 6.2.3 Die implizite Basisklasse java.lang.Object
Pfeil 6.2.4 Einfach- und Mehrfachvererbung *
Pfeil 6.2.5 Die Sichtbarkeit protected
Pfeil 6.2.6 Konstruktoren in der Vererbung und super(…)
Pfeil 6.3 Typen in Hierarchien
Pfeil 6.3.1 Automatische und explizite Typanpassung
Pfeil 6.3.2 Das Substitutionsprinzip
Pfeil 6.3.3 Typen mit dem instanceof-Operator testen
Pfeil 6.4 Methoden überschreiben
Pfeil 6.4.1 Methoden in Unterklassen mit neuem Verhalten ausstatten
Pfeil 6.4.2 Mit super an die Eltern
Pfeil 6.4.3 Finale Klassen und finale Methoden
Pfeil 6.4.4 Kovariante Rückgabetypen
Pfeil 6.4.5 Array-Typen und Kovarianz *
Pfeil 6.5 Drum prüfe, wer sich ewig dynamisch bindet
Pfeil 6.5.1 Gebunden an toString()
Pfeil 6.5.2 Implementierung von System.out.println(Object)
Pfeil 6.5.3 Nicht dynamisch gebunden bei privaten, statischen und finalen Methoden
Pfeil 6.5.4 Dynamisch gebunden auch bei Konstruktor-Aufrufen *
Pfeil 6.5.5 Eine letzte Spielerei mit Javas dynamischer Bindung und überschatteten Attributen *
Pfeil 6.6 Abstrakte Klassen und abstrakte Methoden
Pfeil 6.6.1 Abstrakte Klassen
Pfeil 6.6.2 Abstrakte Methoden
Pfeil 6.7 Schnittstellen
Pfeil 6.7.1 Schnittstellen deklarieren
Pfeil 6.7.2 Implementieren von Schnittstellen
Pfeil 6.7.3 Ein Polymorphie-Beispiel mit Schnittstellen
Pfeil 6.7.4 Die Mehrfachvererbung bei Schnittstellen
Pfeil 6.7.5 Keine Kollisionsgefahr bei Mehrfachvererbung *
Pfeil 6.7.6 Erweitern von Interfaces – Subinterfaces
Pfeil 6.7.7 Konstantendeklarationen bei Schnittstellen
Pfeil 6.7.8 Statische ausprogrammierte Methoden in Schnittstellen
Pfeil 6.7.9 Erweitern von Schnittstellen
Pfeil 6.7.10 Default-Methoden
Pfeil 6.7.11 Erweiterte Schnittstellen deklarieren und nutzen
Pfeil 6.7.12 Erweiterte Schnittstellen, Mehrfachvererbung und Mehrdeutigkeiten *
Pfeil 6.7.13 Bausteine bilden mit Default-Methoden *
Pfeil 6.7.14 Initialisierung von Schnittstellenkonstanten *
Pfeil 6.7.15 Markierungsschnittstellen *
Pfeil 6.7.16 Abstrakte Klassen und Schnittstellen im Vergleich
Pfeil 6.8 Zum Weiterlesen
 
Zum Seitenanfang

6Objektorientierte Beziehungsfragen Zur vorigen ÜberschriftZur nächsten Überschrift

»Aus einer schlechten Verbindung kann man sich schwerer lösen als aus einer guten.«
– Whitney Elizabeth Houston (1963–2012)

Objekte leben nicht in Isolation, sondern in Beziehungen zu anderen Objekten. Was wir uns in diesem Kapitel anschauen wollen, sind die Objektbeziehungen und Typbeziehungen, die Objekte und Klassen/Schnittstellen eingehen können. Im Grunde läuft das auf zwei einfache Beziehungstypen hinaus: Ein Objekt ist mit einem anderen Objekt über eine Referenz verbunden, oder eine Klasse erbt von einer anderen Klasse, sodass die Objekte Eigenschaften von der Oberklasse erben können. Insofern betrachtet das Kapitel Assoziationen für die Objektverbinden und Vererbungsbeziehungen. Darüber hinaus geht das Kapitel auf abstrakte Klassen und Schnittstellen ein, die besondere Vererbungsbeziehungen darstellen, da sie für die Unterklassen Verhalten vorschreiben können.

 
Zum Seitenanfang

6.1Assoziationen zwischen Objekten Zur vorigen ÜberschriftZur nächsten Überschrift

Eine wichtige Eigenschaft objektorientierter Systeme ist der Austausch von Nachrichten untereinander. Dazu »kennt« ein Objekt andere Objekte und kann Anforderungen weitergeben. Diese Verbindung nennt sich Assoziationund ist das wichtigste Werkzeug bei der Bildung von Objektverbänden.

Assoziationstypen

Bei Assoziationen ist zu unterscheiden, ob nur eine Seite die andere kennt oder ob eine Navigation in beiden Richtungen möglich ist:

  • Eine unidirektionale Beziehung geht nur in eine Richtung (ein Fan kennt seine Band, aber nicht umgekehrt).

  • Eine bidirektionale Beziehung geht in beide Richtungen (Raum kennt Spieler und Spieler kennt Raum). Eine bidirektionale Beziehung ist natürlich ein großer Vorteil, da die Anwendung die Assoziation in beliebiger Richtung ablaufen kann.

Daneben gibt es bei Beziehungen die Multiplizität, auch Kardinalität genannt. Sie sagt aus, mit wie vielen Objekten eine Seite eine Beziehung hat oder haben kann. Übliche Beziehungen sind 1:1 und 1:n.

 
Zum Seitenanfang

6.1.1Unidirektionale 1:1-Beziehung Zur vorigen ÜberschriftZur nächsten Überschrift

Damit ein Spieler sich in einem Raum befinden kann, lässt sich in Player eine Referenzvariable vom Typ Room anlegen. In Java sähe das in etwa so aus:

Listing 6.1com/tutego/insel/game/va/Player.java, Player

public class Player {
public Room room;
}

Listing 6.2com/tutego/insel/game/va/Room.java, Room

public class Room { }

Zur Laufzeit müssen natürlich noch die Verweise gesetzt werden:

Listing 6.3com/tutego/insel/game/va/Playground.java, main()

Player buster = new Player();
Room tower = new Room();
buster.room = tower; // Buster kommt in den Tower

Assoziationen in der UML

Die UML stellt Assoziationen durch eine Linie zwischen den beteiligten Klassen dar. Hat eine Assoziation eine Richtung, zeigt ein Pfeil am Ende der Assoziation diese an. Wenn es keine Pfeile gibt, heißt das nur, dass die Richtung noch nicht genauer spezifiziert ist, und nicht automatisch, dass die Beziehung bidirektional ist.

Abbildung 6.1Gerichtete Assoziation im UML-Diagramm

Die Multiplizität wird angegeben als »untere Grenze..obere Grenze«, etwa 1..4. Außerdem lässt sich in UML über eine Rolle angeben, welche Aufgabe die Beziehung für eine Seite hat. Die Rollen sind wichtig für reflexive Assoziationen (auch zirkuläre oder rekursive Assoziationen genannt), wenn ein Typ auf sich selbst zeigt. Ein beliebtes Beispiel ist der Typ Person mit den Rollen Chef und Mitarbeiter.

 
Zum Seitenanfang

6.1.2Zwei Freunde müsst ihr werden – bidirektionale 1:1-Beziehungen Zur vorigen ÜberschriftZur nächsten Überschrift

Diese gerichteten Assoziationen sind in Java sehr einfach umzusetzen, wie wir im Beispiel gesehen haben. Beidseitige Assoziationen erscheinen auf den ersten Blick auch einfach, da nur die Gegenseite um eine Verweisvariable erweitert werden muss. Beginnen wir mit dem Szenario, dass der Spieler seinen Raum und der Raum seinen Spieler kennen soll:

Listing 6.4com/tutego/insel/game/vb/Player.java, Player

public class Player {
public Room room;
}

Listing 6.5com/tutego/insel/game/vb/Room.java, Room

public class Room {
public Player player;
}
Bei bidirektionalen Beziehungen gibt es im UML-Diagramm zwei Pfeile.

Abbildung 6.2Bei bidirektionalen Beziehungen gibt es im UML-Diagramm zwei Pfeile.

Verbinden wir das:

Listing 6.6com/tutego/insel/game/vb/Playground.java, main()

Player buster = new Player();
Room tower = new Room();
buster.room = tower;
tower.player = buster;

So einfach ist es aber nicht! Bidirektionale Beziehungen erfordern etwas mehr Programmieraufwand, da sichergestellt sein muss, dass beide Seiten eine gültige Referenz besitzen. Denn wird die Assoziation auf einer Seite aufgekündigt, etwa durch Setzen der Referenz auf null, muss auch die andere Seite die Referenz lösen:

buster.room = null; // Spieler will nicht mehr im Raum sein

Auch kann es passieren, dass zwei Räume angeben, einen Spieler zu besitzen, doch der Spieler kennt von der Modellierung her nur genau einen Raum:

Listing 6.7com/tutego/insel/game/vb/InvalidPlayground.java, main()

Player buster = new Player();
Room tower = new Room();
buster.room = tower;
tower.player = buster;
Room toilet = new Room();
toilet.player = buster;
System.out.println( buster ); // com.tutego.insel.game.vb.Player@aaaaaa
System.out.println( tower ); // com.tutego.insel.game.vb.Room@444444
System.out.println( toilet ); // com.tutego.insel.game.vb.Room@999999
System.out.println( buster.room ); // com.tutego.insel.game.vb.Room@444444
System.out.println( tower.player ); // com.tutego.insel.game.vb.Player@aaaaaa
System.out.println( toilet.player ); // com.tutego.insel.game.vb.Player@aaaaaa

An der Ausgabe ist abzulesen, dass sich Buster im Tower befindet, aber auch die Toilette sagt, dass Buster dort ist (die Kennungen hinter @ sind für das Buch durch gut unterscheidbare Zeichenketten ersetzt worden. Sie sind bei jedem Aufruf anders).

Die Wurzel des Übels liegt in den Variablen. Variablen können keine Konsistenzbedingungen aufrechterhalten, Methoden können wie in einer Transaktion aber mehrere Operationen durchführen und von einem korrekten Zustand in den nächsten überführen. Daher erfolgt diese Kontrolle am besten mit Zugriffsmethoden, etwa wie setRoom(…) und setPlayer(…).

 
Zum Seitenanfang

6.1.3Unidirektionale 1:n-Beziehung Zur vorigen ÜberschriftZur nächsten Überschrift

Immer dann, wenn ein Objekt mehrere andere Objekte referenzieren muss, reicht eine einfache Referenzvariable vom Typ der anderen Seite nicht mehr aus. Dann sind Datenstrukturen gefragt, die mehrere Referenzen aufnehmen können, etwa dann, wenn sich in einem Raum mehrere Spieler befinden können oder wenn ein Spieler mehrere Gegenstände mit sich trägt. Wir müssen auf der 1-Seite eine Datenstruktur verwenden, die entweder eine feste oder eine dynamische Anzahl anderer Objekte aufnimmt. Eine Handy-Tastatur hat beispielsweise nur eine feste Anzahl von Tasten und ein Tisch nur eine feste Anzahl von Beinen. Bei Sammlungen dieser Art ist ein Array gut geeignet. Bei anderen Beziehungen, wo die Anzahl referenzierter Objekte dynamisch ist, ist ein Array wenig elegant, da die manuellen Vergrößerungen oder Verkleinerungen mühevoll sind.

Dynamische Datenstruktur ArrayList

Wollen wir zum Beispiel erlauben, dass ein Spieler mehrere Gegenstände tragen kann oder eine unbekannte Anzahl Spieler sich in einem Raum befinden können, ist eine dynamische Datenstruktur wie java.util.ArrayList sinnvoller. Genauer wollen wir uns zwar erst in Kapitel 15, »Einführung in Datenstrukturen und Algorithmen«, mit besagten Datenstrukturen und Algorithmen beschäftigen, doch seien an dieser Stelle schon drei Methoden der ArrayList vorgestellt, die Elemente in einer Liste (Sequenz) hält:

  • boolean add( E o ) fügt ein Objekt vom Typ E der Liste hinzu.

  • int size() liefert die Anzahl der Elemente in der Liste.

  • E get( int index ) liefert das Element an der Stelle index.

Ein Raum mit vielen Spielern

Mit diesem Wissen wollen wir dem Raum Methoden geben, sodass er beliebig viele Spieler aufnehmen kann. Für den unidirektionalen Fall ist die Player-Klasse wieder einfach:

Listing 6.8com/tutego/insel/game/vc/Player.java, Player

public class Player {
public String name;

public Player( String name ) {
this.name = name;
}
}

Der Raum bekommt ein internes Attribut players vom Typ der ArrayList:

private ArrayList<Player> players = new ArrayList<Player>();

Dass Angaben in spitzen Klammern hinter dem Typ stehen, liegt an den Java Generics – sie besagen, dass die ArrayList nur Player aufnehmen wird und keine anderen Dinge (wie Geister). Es lässt sich auch noch ein wenig abkürzen:

private ArrayList<Player> players = new ArrayList<>();

Die Details zu Generics sind Teil von Kapitel 10, »Generics<T>«, doch unser Wissen ist an dieser Stelle ausreichend, um die Raum-Klasse fertigzustellen:

Listing 6.9com/tutego/insel/game/vc/Room.java, Room

import java.util.ArrayList;

public class Room {

private ArrayList<Player> players = new ArrayList<>();

public void addPlayer( Player player ) {
players.add( player );
}

public void listPlayers() {
for ( Player player : players )
System.out.println( player.name );
}
}
Room referenziert Player.

Abbildung 6.3Room referenziert Player.

Die Datenstruktur selbst ist privat, und die addPlayer(…)-Methode fügt einen Spieler in die ArrayList ein. Eine Besonderheit bietet die Methode listPlayers(), denn sie nutzt das erweiterte for zum Durchlaufen aller Spieler. Beim erweiterten for ist rechts vom Doppelpunkt nicht nur ein Array erlaubt, sondern auch eine Datenstruktur wie die Liste. Nachdem also zwei Spieler mit addPlayer(…) hinzugefügt wurden, wird listPlayers() die beiden Spielernamen ausgeben:

Listing 6.10com/tutego/insel/game/vc/Playground.java, main()

Room oceanLiner = new Room();
oceanLiner.addPlayer( new Player( "Tim" ) );
oceanLiner.addPlayer( new Player( "Jorry" ) );
oceanLiner.listPlayers(); // Tim Jorry

 


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück
 Zum Katalog
Zum Katalog: Java ist auch eine Insel Java ist auch eine Insel
Jetzt bestellen

 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Java SE 8 Standard-Bibliothek
Java SE 8 Standard-Bibliothek


Zum Katalog: Professionell entwickeln mit Java EE 7
Professionell entwickeln mit Java EE 7


Zum Katalog: Schrödinger programmiert Java
Schrödinger programmiert Java


Zum Katalog: Einführung in Java
Einführung in Java


Zum Katalog: Programmieren lernen mit Java
Programmieren lernen mit Java


Zum Katalog: Apps entwickeln für Android 5
Apps entwickeln für Android 5


Zum Katalog: Apps entwickeln mit Android Studio
Apps entwickeln mit Android Studio


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2016
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de