Implementierung von Datenbehältern Inhaltsverzeichnis Hypertext-Version Ereignissteuerung © APSIS GmbH

5. Werte

Seite 97

Abb. 5.1 Wert im Datenbehälter

5.1. Wertefunktionen

Seite 97

5.1.1. Parametrisierte Mutatoren für statische Objekte

Seite 97

public class WasserUndWein extends lehrbuch.EinEimer { // Applet // (5.1)
	public void start() {
		super.fuellen(super.wasser()); // Parameter ist eine Wertefunktion ¬
		super.entleeren();
		super.fuellen(super.wein()); // eine andere Wertefunktion ¬
		super.entleeren();
	}
}

Abb. 5.2: Aufruf

5.1.2. Parametrisierte Mutatoren für dynamische Objekte

Seite 98

import lehrbuch.*; // (5.2)
public class WasserUndWeinObjekt {
	public static void main(String[] args) {
		try {
			Eimer eimer = new Eimer();
			eimer.fuellen(eimer.wasser()); // Wertefunktion mit Zielobjekt ¬
			eimer.entleeren();
			eimer.fuellen(Eimer.wein()); // Wertefunktion ist static ¬
			eimer.anzeigen(); // erst hier wird der Eimer sichtbar
		} catch ...

Übung 5.1: Ergänzen Sie Ihr Programm aus der Übung 2.16 auf Seite 46 mit Mutatoraufrufen bemalen für Ihre Kreise mit einem der Wertefunktionen rot, gruen oder blau als Parameter, die von der Klasse Kreis exportiert werden.

5.1.3. Inhalt eines Behälters

Seite 99

import lehrbuch.*; // (5.3)
public class EimerInhaltAusgeben {
	public static void main(String[] args) {
		try {
			Eimer eimer = new Eimer();
			eimer.fuellen(Eimer.wein()); // nichts ist sichtbar
			eimer.meldung(); // Ausgabe des Inhalts im Meldungsfenster als Text ¬
		} catch ...

5.2. Funktionen

Seite 99

Unterprogramme Prozeduren Funktionen
Ergebnis void Klasse oder Basistyp
Aufruf als Anweisung Wert als Parameter
return im Rumpf möglich, ohne Wert notwendig, mit Wert
Veränderungen sinnvoll nicht empfohlen
Verwendung als Operation Mutator Informator

Abb. 5.3: Prozeduren und Funktionen

5.2.1. Informatoren für statische Objekte

Seite 100

import lehrbuch.EinEimer; // (5.4) 
public class EimerAusgeben extends EinEimer {
	public void start() { // implizit alles super
		meldung(wasser()); // Ausgabe im Meldungsfenster als Text: "WASSER"
		fuellen(wein());
		meldung(inhalt()); // der aktuelle Inhalt wird im Meldungsfenster ausgegeben ¬
	}
}
public Getraenk inhalt(); // Informator mit dem Ergebnistyp Getraenk

5.2.2. Informatoren für dynamische Objekte

Seite 100

import lehrbuch.*; // (5.5)
public class ZweiEimerAusgeben {
	public static void main(String[] args) {
		try {
			Eimer eimer1 = new Eimer(), eimer2 = new Eimer();
			eimer1.fuellen(Eimer.wasser());
			eimer2.fuellen(Eimer.wein());
			Eimer.meldung(eimer1.inhalt()); ¬
			Eimer.meldung(eimer2.inhalt());
		} catch ... // die Eimer selbst sind hier nicht sichtbar

5.2.3. Implementierung von Informatoren

Seite 101

public class EinEimer extends java.applet.Applet { // (5.6)
		... // Anfang wie im Programm (4.4) auf Seite 80
	public static Getraenk inhalt() throws LeerFehler { // const
		try {
			return eimer.inhalt(); // throws LeerAusn ¬
			// Ergebnis wird von einem Informator geliefert
		}
		catch (lehrbuch.LeerAusn ausnahme) {
			throw new LeerFehler(); // ungeprüfte Ausnahme wird ausgelöst
		}
	}
	...
public class LeerFehler extends java.lang.Error {}; // (5.7)

Übung 5.2: Erweitern Sie die Implementierung ihrer Klasse ToleranterEimer mit Hilfe der Klasse lehrbuch.Eimer aus der Übung 4.1 auf Seite 78 durch die Methode inhalt.

5.2.4. Private Funktionen

Seite 102

private Getraenk berechneterInhalt(); // Profil einer parameterlosen Funktion
import lehrbuch.*; // (5.8)
public class Funktion {
	private static Eimer eimer1 = new Eimer(),eimer2 = new Eimer(),eimer3 = new Eimer();
	private static Getraenk berechneterInhalt(Eimer e1, Eimer e2) { // ¬
		// formale Parameter sind zwei Datenbehälter namens e1 und e2 vom Typ Eimer
		// ihr Ergebnis ist vom Typ Getraenk
		Getraenk g;
		... // berechnen des Ergebnisses
		return g; // das Ergebnis wird dem Aufrufer zurückgegeben ¬
	}
	public static void main(String[] args) {
		try { ... // die Eimer werden angezeigt und gefüllt/entleert
			Eimer.meldung(berechneterInhalt(eimer1, eimer3)); // Aufruf ¬
			eimer1.fuellen(berechneterInhalt(eimer2, eimer3)); // weiterer Aufruf
		} catch ...

5.2.5. Konstante Parameter

Seite 103

private Getraenk berechneterInhalt(final Eimer e1, final Eimer e2) { // const e1, e2

5.3. Duplizieren von Inhalten

Seite 103

5.3.1. Kopie

Seite 103

import lehrbuch.*; // (5.9) 
public class InhaltKopieren {
	public static void main(String[] args) {
		try {
			Eimer eimer1 = new Eimer(), eimer2 = new Eimer();
			... // beide Eimer anzeigen
			eimer1.fuellen(Eimer.wasser());
			eimer2.fuellen(eimer1.inhalt()); // hier wird kopiert ¬
		} catch ...
eimer2.fuellen(inhalt(eimer1));
eimer2.kopieren(eimer1); // schon im Programm (3.9) vorgestellt

Übung 5.3: Ergänzen Sie Ihr Programm aus der Übung 5.1 auf Seite 99 mit einem Aufruf, durch den der Inhalt eines Ihrer Kreise in einen anderen kopiert wird. Dazu brauchen Sie den Informator inhalt der Klasse lehrbuch.Kreis. Da der Informator ein Objekt der Klasse lehrbuch.Farbe liefert, können Sie den Aufruf genau an der Position einsetzen, wo auch Farbwerte stehen können. Das Ergebnis des Kopiervorgangs sehen Sie: Ihre beiden Kreise zeigen dieselbe Farbe.

5.3.2. Zuweisung

Seite 104

ziel = quelle; // zwei Referenzen vom selben Typ
import lehrbuch.*; // (5.10)
public class EimerZuweisen {
	public static void main(String[] args) {
		try {
			Eimer eimer1 = new Eimer(), eimer2 = new Eimer();
			... // beide Eimer anzeigen
			eimer1.fuellen(Eimer.wasser());
			eimer2.fuellen(Eimer.wein());
			eimer2 = eimer1; // Referenz wird kopiert, keine Veränderung sichtbar ¬
			eimer2.entleeren(Eimer.wasser()); // das erste Objekt wird verändert! ¬
		} catch ...

5.3.3. Klonen

Seite 105

protected Object clone() throws CloneNotSupportedException;
Eimer eimer1 = new Eimer(); // (5.11)
eimer1.anzeigen();
	... // fuellen und/oder entleeren
Eimer eimer2 = (Eimer)eimer1.clone(); // ein neues Objekt mit dem gleichen Inhalt ¬
eimer2.fuellen();
class Klasse implements Cloneable {
	public Object clone() {
		try {
			return super.clone(); // Objektinhalt wird kopiert
		} catch(CloneNotSupportedException ausnahme) { // kann nicht auftreten
			System.err.println(ausnahme);
	}
	...
public Object clone() {
		Eimer neuerEimer = super.clone();
		// Eimer neuerEimer = new Eimer(); // alternativ
		... // Algorithmus, um den geklonten Eimer in den Anfangszustand zu bringen
		return neuerEimer;
}
Eimer eimer2 = (Eimer)eimer1.clone(); // ein neues Objekt mit dem gleichen Inhalt ¬
public Eimer klonen() {
	Eimer neuerEimer = new Eimer();
	// Eimer neuerEimer = super.clone();
		// alternativ; funktioniert, nur wenn class Eimer implements Cloneable
	... // Algorithmus, um den geklonten Eimer in den Anfangszustand zu bringen
	return neuerEimer;
}

5.4. Profilkompatibilität

Seite 106

5.4.1. Profilkompatibilität beim Aufruf

Seite 107

import lehrbuch.*; // Eimer, VollAusn, LeerAusn // (5.12)
public class FuellenNachEntleeren extends java.applet.Applet {
	private void fuellenNachEntleeren(final Eimer quelle, Eimer ziel) throws LeerAusn, ¬
			VollAusn {
		// der Eimer ziel wird mit dem Inhalt des Eimers quelle gefüllt, nachdem entleert
		ziel.entleeren();
		ziel.fuellen(quelle.inhalt());
	}
	...

Abb. 5.4: Parameter

Übung 5.4: Definieren Sie in Ihrem Programm aus der Übung 5.1 auf Seite 99 eine Prozedur, die den in ihrem Parameter angegebenen Kreis nacheinander in drei verschiedenen Farben (Ihrer Wahl) malt. Rufen Sie Ihre Prozedur je zweimal für Ihre beiden Kreise auf. Definieren Sie eine zweite Prozedur mit zwei Parametern (Zielkreis und Quellkreis), die in den Zielkreis die Farbe eines zweiten (Quell-)Kreises hineinkopiert und anschließend die Farbe des Quellkreises verändert. Rufen Sie auch diese Prozedur mit verschiedenen Parameterkombinationen auf: Auch mit dem gleichen Kreis in beiden Parametern.

5.4.2. Signaturidentität

Seite 108

Überladen (overload).

class Klasse {
	public Object clone() { ... } // Kopieralgorithmus
public Klasse clone(String zeichenkette) { ...

5.5. Verwendung von Informatoren

Seite 109

5.5.1. Standardinformatoren

Seite 109

public class Abspielen extends java.applet.Applet { // (5.13)
	public void init() {
		super.play(super.getCodeBase(), "hallo.au"); ¬
	}
}

5.5.2. Geschachtelte Informatoraufrufe

Seite 110

public class Malen extends java.applet.Applet { // (5.14)
	public void paint(java.awt.Graphics grafik) {
		grafik.drawImage(super.getImage(super.getCodeBase(), "Hallo.gif"), 0, 0, this); // ¬
			// geschachtelter Informatoraufruf
	}
}

Abb. 5.5: Geschachtelte Aufrufe

public void drawImage(java.awt.Image img, int x, int y,
	java.awt.image.ImageObserver observer)

5.5.3. Informatoren als Objektlieferanten

Seite 111

public class MalenUngeschachtelt extends java.applet.Applet { // (5.15)
	public void paint(java.awt.Graphics grafik) {
		java.awt.Image bild = super.getImage(super.getCodeBase(), "Hallo.gif"); // lokal ¬
		grafik.drawImage(bild, 0, 0, this); // lokale Referenz benutzt
	}
}
public class MalenOptimal extends java.applet.Applet { // (5.16)
	private java.awt.Image bild; // globale Referenz, benutzbar nur in dieser Klasse ¬
	public void init() {
		bild = super.getImage(super.getCodeBase(), "Hallo.gif");
	}
	public void paint(java.awt.Graphics grafik) {
		grafik.drawImage(bild, 0, 0, this); // globale Referenz bild benutzt ¬
	}
}

Übung 5.5: Erweitern Sie das Programm (5.13) auf Seite 110, indem die Audiodatei nicht nur einmal abgespielt wird, sondern jedes Mal, wenn die Methode paint aufgerufen wird. Sie sollen sie hierzu mit Hilfe des Informators getAudioClip aus der Klasse java.applet.Applet einmal (bei init) laden und mit Hilfe der parameterlosen Methode play aus der Klasse java.applet.AudioClip abspielen (eine Methode mit dem selben Namen ist auch in der Klasse java.applet.Applet enthalten). getAudioClip aus der Klasse java.applet.Applet muss mit zwei Parametern aufgerufen werden: einem URL und einem String – ähnlich wie play im Programm (5.13) auf Seite 110. Er liefert ein Objekt der Klasse java.applet.AudioClip. Für dieses Objekt kann play parameterlos aufgerufen werden.

Benutzen Sie in Ihrem Programm kein import, damit der Ursprungsort aller Methoden eindeutig sichtbar ist.

Übung 5.6: Kombinieren Sie nun Ihre Fähigkeiten, mit Hilfe von Standardklassen Audiodateien abzuspielen und Grafiken anzuzeigen. Erweitern Sie Ihre Lösung aus der vorherigen Übung, indem Sie sowohl eine Grafik anzeigen wie auch zwei Audiodateien abspielen. Die erste Audiodatei sollten Sie beim start, die Zweite beim stop (d.h. beim Verlassen des Applets) abspielen.

5.5.4. Spezifikation von Informatoren

Seite 113

package lehrbuch; // (5.17)
public class EinEimer { // statischer Datenbehälter
	public static Getraenk wasser(); // erste Wertefunktion
	public static Getraenk wein(); // zweite Wertefunktion
	public static Getraenk inhalt() throws LeerFehler; // const // Informator ¬
	public static void meldung(final Getraenk getraenk) throws LeerFehler; // const ¬
	public static void fuellen() throws VollFehler; // parameterlose Version
	public static void fuellen(final Getraenk getraenk) throws VollFehler; ¬
	... // weitere Teile der Spezifikation, s. Programm (3.10)
public class Eimer { // dynamischer Datenbehälter // (5.18)
	public static Getraenk wasser(); // Wertefunktionen static
	public static Getraenk wein();
	public void fuellen() throws VollAusn; // nicht mehr static
	public void fuellen(final Getraenk getraenk) throws VollAusn; ¬
	public void entleeren() throws LeerAusn;
	public Getraenk inhalt() throws LeerAusn; ¬
	public void anzeigen() throws LeerAusn; // const
	public static void meldung(final Getraenk getraenk); // const getraenk
	public void meldung() throws LeerAusn; // const
}
package java.applet; // (5.19)
public class Applet {
	public void play(java.net.URL url, java.lang.String name);
	// Informatoren:
	public AudioClip getAudioClip(java.net.URL url, String name);
	public java.net.URL getCodeBase();
	public java.awt.Image getImage(java.net.URL url, String name);
	// die fünf Methoden stellen den Lebenszyklus eines Applets dar (zum Überschrieben)
	public void init();
	public void start();
	public void stop();
	public void paint(java.awt.Graphics g);
	public void destroy();
		...
package java.awt; // (5.20)
public class Graphics {
	public void drawImage(java.awt.Image img, int x, int y,
		java.awt.image.ImageObserver observer);
	public void drawString(java.lang.String str, int x, int y);
		...

5.5.5. Werte als Referenzen

Seite 114

import lehrbuch.EinEimer; // (5.21)
public class WertAlsReferenz extends EinEimer {
	public void start() {
		fuellen(WASSER); // WASSER ist eine Wertreferenz ¬
	}
}
package lehrbuch; // (5.22)
public class EinEimer {
	public final static Getraenk WASSER; // Wertereferenzen
	public final static Getraenk WEIN;
	...
public class Eimer { // (5.23)
	public static Getraenk wasser() {
		return WASSER; // WASSER ist hier private
	}
	...

Übung 5.7: Ergänzen Sie Ihr Applet aus der Übung 3.8 auf Seite 75, indem Sie darin dem Mutator setColor der Klasse Graphics die Wertereferenzen red, green und blue der Standardklasse java.awt.Color als Parameter übergeben.

5.5.6. Export und Import

Seite 115

Abb. 5.6: Export und Import

import lehrbuch.EinEimer; // (5.24)
public class ImportierterWert extends EinEimer {
	public void start() {
		fuellen(WASSER); // fuellen und wasser stammen aus EinEimer ¬
		entleeren(); // entleeren ebenfalls, durch import wird erkannt
	}
}

Implementierung von Datenbehältern Inhaltsverzeichnis Hypertext-Version Ereignissteuerung © APSIS GmbH