Nochmal zum Einkaufszettel: werde interaktiv!
Stell’ dir eine Welt vor, in der du einem laufenden Programm etwas mitteilen könntest. Wäre das nicht schön?
Das wäre es! Und das wirst du heute hinbekommen! Gleichzeitig wirst du etwas darüber lernen, wie deine Klassen zusammenarbeiten können.
Gut aufgepasst – ja, das stimmt! Die Objekte, die von den Klassen abgeleitet werden, arbeiten miteinander. In den Klassen sind diese Beziehungen aber natürlich schon angelegt.
In gewisser Weise: gar nicht!
Ja, schon… aber hast du schon mal gehört, dass ein Einkaufszettel fragt, ob du noch etwas auf ihn draufschreiben möchtest?
Eben! Die Klasse Einkaufszettel ist so wie sie ist ganz in Ordnung. Was wir eigentlich haben möchten, ist so eine Art Helfer, der uns danach fragt, und dann den Einkaufszettel für uns verwaltet. Und eine solche Klasse werden wir schreiben!
Wir brauchen also unsere Klasse Einkaufszettel, und schreiben eine neue Klasse, die uns mit der Bedienung hilft.
Er könnte schon. Wenn du dein Programm allerdings später noch erweitern möchtest, wird das Modell, das unsere Klassen bilden, immer schwammiger und unschärfer. Daher solltest du darauf achten, deine Klassen gut zu benennen und in ihnen nur das zu programmieren, für das ihr Name auch steht. So wirst du einen besseren Überblick behalten können.
Wir starten mit einer Übung, die dir schon bekannt vorkommen sollte. Stell dir einen Timer auf drei Minuten, und sieh’ dir unsere Klasse Einkaufszettel noch einmal an. (Der Code erscheint, sobald du auf den nächsten Button klickst.) Minimiere dann dieses Fenster, und versuche den Code aus dem Gedächtnis aufzuschreiben. Bereite dafür am besten zuvor einen neuen Workspace in der Online-IDE vor, in diesem werden wir dann weiterprogrammieren.
public class Einkaufszettel {
private ArrayList<String> einkauf = new ArrayList<>();
public void einkaufHinzufügen(String artikel) {
this.einkauf.add(artikel);
}
public void druckeListe() {
for (String art : this.einkauf) {
println(art);
}
}
public void druckeNummerierteListe() {
for (int i=0; i<this.einkauf.size(); i++) {
println(i + ": " + this.einkauf.get(i));
}
}
}
Wenn du allen Code, an den du dich erinnern konntest, aufgeschrieben hast, kann es weitergehen.
Vergleiche nun und überlege:
Welche Teile konntest Du korrekt wiedergeben?
Gibt es Teile, die unvollständig sind?
Verstehst Du, warum Du Zeilen ausgelassen hast?
Verstehst Du, was in den Zeilen, die Du ausgelassen hast, passiert?
Falls noch nicht geschehen, schreibe dir für die Teile, die du dir schlecht merken konntest, Karteikarten.
Dann kann es losgehen. Lege eine Datei EinkaufHelper.java im gleichen Workspace an, und beginne mit der Klassendefiniton:
public class EinkaufHelper {
}
Füge nun der Klasse eine Instanzvariable zettel vom Typ Einkaufszettel hinzu. Weil wir bei dieser einfachen Klasse keinen extra Konstruktor schreiben wollen, sollst du den Einkaufszettel in der gleichen Zeile erzeugen.
Der Code, den wir zu diesem Zweck der Klasse hinzufügen, ist nur eine Zeile lang:
public class EinkaufHelper {
private Einkaufszettel zettel = new Einkaufszettel();
}
Kannst du den Code richtig zuordnen? Dann solltest du alles verstanden haben.
Wofür steht z.B. das Wort zettel
hier?
Nein, das ist lediglich der Name der Variable, die wir hier anlegen.
Ja, das stimmt!
Nein, das ist lediglich der Name der Variable, die wir hier anlegen.
Und was macht new Einkaufszettel()
in dieser Zeile?
Nein, new
erzeugt den Einkaufszettel!
Nein, new
erzeugt den Einkaufszettel!
Sehr schön!
Und was bedeutet das Wort Einkaufszettel
nach dem Wort private
?
Jawohl! Außerdem ist die Variable privat, was sich am Wort private
ablesen lässt.
Nein, damit wird der Typ festgelegt.
Nein, damit wird der Typ festgelegt.
Als nächstes sollst du eine Methode schreiben, die den Nutzer oder die Nutzerin solange nach weiteren Artikeln fragt, bis die Eingabe »Ende« ist. Diese Artikel sollen nach und nach der Liste, die wir gerade angelegt haben, hinzugefügt werden.
Dazu kannst du die Klasse Input
verwenden, die in der Online-IDE zur Verfügung steht. Die Klasse ist etwas besonderes, denn du musst, um sie nutzen zu können, kein Objekt von ihr erzeugen. (Programmierer_innen sagen dazu, die Klasse habe statische Methoden.)
Du kannst an ihr die Methode readString
aufrufen. Diese Methode nimmt eine Zeichenkette entgegen, gibt diese aus, und wartet dann auf eine Eingabe. Sobald die Eingabe mit der Eingabetaste abgeschlossen wurde, gibt sie diese Eingabe als Zeichenkette zurück.
Möchtest du ein Beispiel sehen?
In Ordnung. Tippe diese Zeilen einmal in eine neue Datei in der Online-IDE, und lass sie laufen:
String antwort = Input.readString("Wie heißt du?");
println("Hallo " + antwort);
Auf diese Weise lässt sich eine Eingabe einlesen und in der Variablen antwort abspeichern. Die zweite Zeile begrüßt lediglich den eingegeben Namen.
Versuche nun, eine Methode frageNachArtikel()
zu schreiben! Es genügt zunächst, wenn die Methode nach einem einzigen Artikel fragt, und diesen dann der Liste this.zettel
hinzufügt. Versuche es zuerst alleine, und sieh’ dir dann den Lösungsvorschlag an.
Die Klasse EinkaufHelper
sollte nun so aussehen:
public class EinkaufHelper {
private Einkaufszettel zettel = new Einkaufszettel();
public void frageNachArtikeln() {
String antwort = Input.readString("Welcher Artikel soll auf die Liste?");
this.zettel.einkaufHinzufügen(antwort);
}
}
Wenn nun solange nach weiteren Artikeln gefragt werden soll, bis das Wort »Ende« eingetippt wird – wie würdest du das in der Methode aufschreiben?
Ja, das ist eine gute Idee!
Am besten verwendest du eine while
-Wiederholung! Nach dem Schlüsselwort while
wird eine Bedingung überprüft, und so lange diese Bedingung zu wahr (true
) ausgewertet wird, wird der Code im nachfolgenden, von geschweiften Klammern umschlossenen Codeblock ausgeführt. Wieder, und wieder, und wieder…
Z.B. so:
while (true) {
// das wird deinem Computer eine Weile zu denken geben…
}
Das stimmt – dafür steht der Wahrheitswert true
in der Klammer. An Stelle dieses Wahrheitswertes kannst du beliebige Bedingungen überprüfen.
Die while
-Wiederholung kommt dir vielleicht noch bekannt vor. Wenn du sie einige Male geschrieben haben wirst, wirst du dich sicher wieder gut erinnern können.
Das wäre eine Möglichkeit. Noch geeigneter wäre die Methode equals
, die sich an Strings aufrufen lässt. Und hier noch besser, weil benutzerfreundlicher, ist die Methode equalsIgnoreCase
, der die Groß- und Kleinschreibung egal ist.
Versuche nun, die Methode frageNachArtikeln
so zu erweitern, dass so lange Artikel eingelesen werden, bis das Wort »Ende« eingetippt wird. Sieh’ dir den Lösungsvorschlag erst an, wenn du deine Methode fertig hast, oder dir nichts mehr einfällt!
Die Klasse EinkaufHelper
könnte nun z.B. so aussehen:
public class EinkaufHelper {
private Einkaufszettel zettel = new Einkaufszettel();
public void frageNachArtikeln() {
println("Tippe 'Ende', wenn du beenden möchtest.");
boolean sollWeiterfragen = true;
while (sollWeiterfragen) {
String antwort = Input.readString("Welcher Artikel soll auf die Liste?");
if(antwort.equalsIgnoreCase("ende")) {
sollWeiterfragen = false;
} else {
this.zettel.einkaufHinzufügen(antwort);
}
}
}
}
Andere Lösungen sind denkbar – so könntest du z.B. direkt überprüfen, ob die Antwort nicht »Ende« ist. Möchtest du eine solche Lösung sehen?
public void frageNachArtikeln() {
println("Tippe 'Ende', wenn du beenden möchtest.");
String antwort = Input.readString("Welcher Artikel soll auf die Liste?");
while (!antwort.equalsIgnoreCase("ende")) {
this.zettel.einkaufHinzufügen(antwort);
antwort = Input.readString("Welcher Artikel soll noch auf die Liste?");
}
}
Hier wird das nicht mit dem Operator !
formuliert. Insgesamt ist diese Lösung kürzer als die erste, aber vielleicht auch ein bißchen unübersichtlicher. Welche Variante du wählst, ist letztlich auch Geschmackssache. (Ich versuche, meist die zu wählen, die klarer nachvollziehbar ist – aber auch da kann es subjektiv unterschiedliche Ansichten geben.)
Nun fehlt nur noch eine Methode, die unsere Helper-Klasse dazu bewegt, den Einkaufszettel ausgeben zu lassen. Kommst du damit zurecht?
Das ist zwar richtig, doch ist unsere entsprechenden Instanzvariable ja private – von außen kommen wir gar nicht heran!
Wenn du deine Lösung fertig hast, vergleiche sie mit dem Lösungsvorschlag.
Der Lösungsvorschlag ist nicht spektakulär, er ergänzt den Aufruf der Einkaufszettel-Methode lediglich um eine einleitende Zeile. (Achte darauf, dass du die Methode noch innerhalb der Klasse EinkaufHelper aufschreibst.)
public void lasseListeAusgeben() {
println("Jetzt befinden sich auf dem Einkaufszettel:");
this.zettel.druckeNummerierteListe();
}
Wenn du nun in einer Start-Datei im gleichen Workspace ein EinkaufHelper-Objekt erzeugst, und daran die beiden Methoden frageNachArtikeln
und lasseListeAusgeben
, kannst du den Einkaufszettel interaktiv verwenden.
Nicht spektakulär…
EinkaufHelper edi = new EinkaufHelper();
edi.frageNachArtikeln();
edi.lasseListeAusgeben();
Gut! Damit haben wir einen interaktiven Einkaufszettel!
Neue Vokabeln in dieser Lektion
Schreibe den entsprechenden Code auf, und überprüfe, ob du richtig liegst! (Diesmal ist noch eine Extra-Übung enthalten, die in der Lektion nicht behandelt wurde.)
Schreibe in zwei Zeilen auf, wie sich in der Online-IDE eine Antwort einlesen und wieder ausgeben lässt. Gefragt werden soll nach dem Namen.
String antwort = Input.readString("Wie heißt du?");
println("Hallo " + antwort);
Schreibe eine Klasse Buch mit einer privaten Instanzvariablen kapitel, die gleich nach der Deklaration mit einer ArrayList vom Typ String initialisiert wird.
public class Buch {
private ArrayList<String> kapitel = new ArrayList<>();
}
Schreibe eine Klasse Buch mit einer privaten Instanzvariablen kapitel, die in einem Konstruktor mit einer ArrayList vom Typ String initialisiert wird.
public class Buch {
private ArrayList<String> kapitel;
public Buch() {
this.kapitel = new ArrayList<>();
}
}
Schreibe eine while-Wiederholung, die solange läuft, wie die am Objekt game aufgerufene Methode isRunning true
zurückgibt. (Der umschließende Codeblock kann leer bleiben.)
while (game.isRunning()) {
// hier wird irgendwelcher Code ausgeführt
}