 |
9. Eigene Klassen
|
|
| |
Bis hierher haben Sie
ausschliesslich Klassen verwendet, welche aus der Klassenbibliothek
des SDK stammen (einzig die Programme selber waren ja eigene Klassen).
Jetzt sollen Sie Ihre eigenen Klassen basteln und sie dann verwenden.
Das Beispiel, an welchem Sie die Sache üben sollen, ist wieder
das Thema Farben: Sie machen eine Eigene Farb - Klasse mit Ihrer
(bzw. meiner) Lieblingsfarbe:
Ihre eigene Klasse MyColor ist
offenbar eine Unter-Klasse von Color. Mit "extends" zeigen Sie das
an. Color ist also die Super-Klasse von MyColor, von der MyColor
alles erbt. Ihre eigene Klasse erweitert Color nur ganz wenig, nämlich
mit einem speziellen Konstruktor. Einen Konstruktor
definieren Sie, indem Sie den Klassennamen schreiben, gefolgt von
runden Klammern. In der anschliessenden geschweiften Klammer definieren
Sie den Konstruktor, sagen also, was geschehen soll, wenn eine Instanz
Ihrer Klasse erzeugt wird. Unser Konstruktor hier ist sehr einfach:
er ruft einen Konstruktor der Superklasse auf, nämlich den mit
den drei Integer Zahlen in der Klammer. Das Schlüsselwort super steht
dabei für den Namen der Superklasse, in unserem Falle
Color. Maximal rot und maximal blau ergibt Magenta. MyColor()
erzeugt offenbar
die Farbe Magenta.
- Übersetzen Sie die Klasse
MyColor (Menü Build, Compile File)
.
- Öffnen Sie die Klasse Farben
wieder und deklarieren Sie die Hintergrundfarbe anstatt vom Typ
Color nun als vom Typ MyColor. Bei mir heisst das MyColor
hinter;. Das Erzeugen der Instanz geschieht
mit hinter = new MyColor();. Sie dürfen
nichts in die runde Klammer schreiben, denn Ihr Konstruktor hat
auch nichts in der runden Klammer. Das wäre bei Color nicht
erlaubt: alle Konstruktoren von Color haben etwas in der runden
Klammer und dieses etwas sind die Parameter.
- Übersetzen Sie auch die Klasse
Farben
und lassen Sie das Applet laufen: Wenn der Hintergrund in
Magenta erscheint, hat's geklappt.
- Ergänzen Sie jetzt Ihre Klasse
MyColor durch den folgenden zweiten Konstruktor:
MyColor(int verdunkeln)
{
super(255-verdunkeln,0,255-verdunkeln);
}
Dieser Konstruktor hat jetzt
einen Parameter namens verdunkeln, welcher den Konstruktoraufruf für
Color beeinflusst. Sie können so viele Konstruktoren definieren
wie Sie wollen. Einzige Bedingung: Die Parameter der Konstruktoren
müssen sich voneinander unterscheiden; es kann die Zahl der Parameter
verschieden sein, aber auch nur der Typ.
- Übersetzen Sie die
Klasse MyColor wieder. Übrigens: Sie brauchen sich eigentlich gar
nicht zu merken, welche Datei nun übersetzt werden muss: Wenn Sie
Menü Build, Compile Project wählen (oder die Taste <F7> drücken,
dann schaut JCreator selber nach, welche Dateien des Projektes
geändert wurden und übersetzt werden müssen.
|
|
| |
- Ändern Sie in Farben
die Instanzierung so ab, dass Sie den neuen Konstruktor von MyColor
verwenden, z.B. hinter
= new MyColor(150);.
Damit erzeugen Sie eine Hintergrundfarbe Color(105,0,105) und Ihr
Applet sollte nach Kompilation und Ausführung einen dunkeln
Magenta - Hintergrund haben. Selbstverständlich können
Sie in Farben gleichzeitig auch den ursprünglichen Konstruktor
ohne Parameter verwenden um eine helle Magentafarbe z.B. für
den Vordergrund zu erzeugen. Mein Applet sieht dann so wie das Bild
rechts aus.
-
Die neue
Klasse MyColor soll nun aber nicht nur die Eigenschaft haben,
dass sie magenta
ist, sie soll auch was können. Fähigkeiten verpassen
Sie einer Klasse, indem Sie Methoden definieren. Schreiben
Sie hinter den Konstruktoren von MyColor die folgende Methode:
String farbName() {
return "Magenta";
}
-
Die
Methode farbName() ist vom Typ String. Das heisst, dass
sie nach ihrer Ausführung
einen Wert von diesem Typ zurückgibt. Methoden, die von einem
Typ sind müssen eine letzte Anweisung mit dem Schlüsselwort return haben.
Hinter return steht, was die Methode zurückliefert, in unserem
Falle ist das die String - Konstante "Magenta". Sie könnten
nun in der Klasse Farben die Methode z.B.
aufrufen mit String
s = hinter.farbName();.
Sie können
diesen String aber auch direkt in das Applet schreiben, z.B. mit g.drawString(vorder.farbName(),120,150);.
Versuchen Sie's, aber passen Sie auf, dass
Sie nicht etwa mit der Hintergrundfarbe
auf Hintergrundfarbe schreiben oder ähnlich!
Auch Variablen kann
Ihre Klasse natürlich enthalten. Die Farbe könnte
sich z.B. merken ob sie
dunkel ist oder nicht.
Also deklarieren Sie
am Anfang von MyColor boolean dunkel; In
den Konstruktoren ergänzen
Sie dann nach der Anweisung
super(...); mit dunkel = false; bzw. dunkel
= true;.
Die Methode kann nun je
nach dem zwei verschiedene
Strings zurückgeben,
z.B. folgendermassen:
if
(dunkel) return "Dunkelmagenta"; else return "Magenta";
Und
in Farben können
Sie nacheinander die
Vorder- und Hintergrundfarbe
herausschreiben.
Versuchen Sie's!
Das Wichtigste habe ich bei
der Sache unterschlagen: Die Variablen wie z.B. dunkel, sollten unbedingtprivate deklariert
werden, also z.B.:
private boolean dunkel;. Es
hat zwar alles bestens funktioniert. Könnte aber sein, dass irgendein Programmierer
(vielleicht Sie selber) den Wert der Variablen abändert (z.B. aus Versehen).
Variablen und auch Methoden, die Sie mit dem Qualifizierer private versehen,
sind nur in derjenigen Klasse bekannt, in der sie deklariert wurden. So kann
ihnen nichts Böses geschehen und sie sind gegen aussen
geschützt, man sagt dem auch abgekapselt.
Sie sollten immer alles abkapseln, was nicht nach aussen bekannt sein muss.
In unserem Falle ist das die Variable. Die Methode müssen wir von aussen, aus
der Klasse Farben heraus, verwenden können. Also darf sie nicht private
sein. Es ist ein guter Stil, nach Möglichkeit Variablen private zu deklarieren
und ihre Werte mit Hilfe von Methoden nach aussen
verfügbar zu machen - so wie ich es Ihnen soeben vorgeführt habe.
Gerade die Tatsache, dass man in Klassen Dinge abkapseln kann, macht das
objektorientierte
Programmieren so erfolgreich.
|
 |
| |
- Wie
wär's, wenn sich die Farbe nicht nur merken würde
ob sie verdunkelt ist, sondern auch noch um wieviel? Deklarieren
Sie dazu eine zweite Variable, geben sie ihr im Konstruktor
den richtigen Wert, schreiben Sie eine zweite Methode,
welche diesen Wert liefert und schreiben Sie ihn ins Applet.
Das könnte dann etwa so aussehen:
Falls Sie allzusehr Mühe haben
mit diesem Programm: meine Lösung finden Sie hier.
Drucken Sie die Besprechung.
Noch zwei Ergänzungen:
Fields:
Variablen, welche in einer Klasse deklariert sind heissen Felder
oder fields, im Unterschied zu Variablen, welche in Methoden deklariert
sind (was offenbar auch möglich ist!). Fields sind in der ganzen
Klasse bekannt, Variablen einer Methode aber nur in der Methode selber.
Vordefinierte Farben:
In der Klasse Color sind eine Reihe gebräuchlicher Farben als
fields schon vordefiniert.
- Klicken Sie irgendwo
auf das Wort Color im Editor, drücken Sie die Tastenkombination <Ctrl>+<F1>,
scrollen Sie dort bis zum "Field
Summary": Sie sehen alle vordefinierten Farben. Sie können
also z.B. mit setBackground(Color.pink); die
Hintergrundfarbe auf rosa setzen - probieren Sie's aus, wenn Sie
Lust haben
|

|
| |
Spielereien
mit Bildern: Ich habe schon erwähnt, dass man in Applets besonders
einfach
Bilder einfühgen kann. Bilder sind Instanzen der Klasse Image.
Ein Bild holen Sie in ein Applet mit der Methode getImage(), deren Rückgabewert
eine Instanz von Image ist. Eine kleine Komplikation: Der Parameter von getImage()
ist eine URL (Webadresse, dazu später mehr). Die URL der .htm Datei des Applets
liefert getDocumentBase() (ohne Dateiname). Den Dateinamen können Sie bei
getImage() als zweiten Parameter als String angeben. Konkret sieht das dann
folgendermassen aus:
- Erstellen Sie
ein neues Applet Projekt oder ändern Sie das Projekt Farben ab.
- Kopieren Sie das
Bild smilyCrazy.jpeg oder
ein anderes .jpg oder .gif Bild in den Ordner classes.
- Deklarieren Sie
im Applet eine Image - Variable, z.B. Image img;
- In die Methode
init() kommt folgende Anweisung: img = getImage(getDocumentBase(),"smilyCrazy.jpeg");
init() wird übrigens beim
Start des Applet ausgeführt!
- In der Methode
paint() schreiben Sie dann g.drawImage(img,0,0,this);
- Übersetzen Sie
und führen Sie aus: Schon sollte das crazy Smily zu sehen sein!
- So etwas wie das
Bild rechts erhalten Sie, wenn Sie das Bild z.B. 100 mal in einer
for Schlaufe darstellen, an verschiedenen Positionen. Denken Sie
an die Methode Math.random(),
welche Ihnen Zufallszahlen zwischen 0 und 1 liefert und dass Sie
so eine Fliesskommazahl mit (int) in einen Integer umwandeln
können
- Lustig sieht die
Sache übrigens aus, wenn Sie das Bild in einem unendlichen Loop immer
wieder darstellen. Speichern Sie vorher alles. Einen unendlichen
Loop erhalten Sie z.B. mit while (true). Sie stoppen
das Applet am besten im schwarzen Fenster mit <Ctrl>+<c>.
- Noch psychedelischer
wird's, wenn Sie Musik abspielen dazu:
play (getDocumentBase(), "spacemusic.au");
Die Audiodatei spacemusic.au muss wie das
Bild im Ordner classes sein. Damit Sie was hören muss ich Ihnen einen
Kopfhörer aus dem Schrank geben. Leider kann das Stück mit unseren
Kenntnissen nur einmal abgespielt werden. Hier wäre noch eine Wave
- Datei: CHIMES.WAV. Und hier noch eine MIDI
Datei: Mond.mid. Auf direktem Weg können wir
leider keine .mp3 Dateien abspielen, aber sonst haben wir jetzt schon
(fast!!!) unseren eigenen Mediaplayer. Mehr zu Bildern und Musik folgt
später.
|

|
| |
|
|