Java: Polymorphie & Paketstruktur
06.04 2008 07:48
Neue Aufgabe - neues Glück :P In dieser Aufgabe ist der Schreibaufwand schon ein bisschen höher als bei der vorhergehenden, aber dennoch mit relativ geringem Aufwand zu meistern.
In der Teilaufgabe A sollen wir die Klasse Artikel um ein paar Methoden, sowie Eigenschaften erweitern. Ähnliches soll in B der Klasse Videothek angetan werden. In C wird das Neue und Alte in Paketform gebracht und die Teilaufgabe D verlangt von uns, dass wir das alles Testen. Die Bonusaufgabe E wird dem ganzen auch noch angehängt ;)
Lange Rede - kurzer Sinn.
A:
So. Hier soll nun, die aus Aufgabe 1 existierende Klasse Artikel, erweitert werden.
Um die Eigenschaft (Variable) availableArticles, die die Anzahl der verfügbaren Artikel widerspiegelt:
private int availableArticles;
Um die Methode getAvailableArticles, mit der man die Anzahl der verfügbaren Artikel auslesen kann:
public int getAvailableArticles()
{
return availableArticles;
}
Um die Methode decrementArticle, die die Anzahl der verfügbaren Artikel um Eins verringert:
public void decrementArticle()
{
availableArticles--;
}
Und um die Methode incrementArticle, die die Anzahl der verfügbaren Artikel um x erhöht:
public void incrementArticle(int x)
{
availableArticles += x;
}
B:
Ähnliches wird nun mit der Klasse Videothek gemacht:
Ein Array artikelliste vom Typ Artikel wird hinzugefügt:
private Artikel[] artikelliste = new Artikel[0];
Ebenso die Methode deleteArticle, die den Artikel mit der Position articleNr im Array löscht:
public void deleteArticle(int articleNr)
{
if(articleNr >= 0 && articleNr < artikelliste.length){
Artikel tmp[] = new Artikel [artikelliste.length-1];
int cnt = 0;
for(int i = 0; i < artikelliste.length; i++)
{
if(i != articleNr)
{
tmp[cnt++] = artikelliste[ i ];
}
}
artikelliste = tmp;
} else {
System.out.println("Ungültige Löschanfrage.");
}
}
Zuerst wird geprüft, ob der übergebene Löschparameter gültig ist. Danach wird ein neues Array tmp erstellt, dem alle Elemente von artikelliste eingetragen werden, die nicht dem zu löschenden entsprechen. Nun wird artikelliste mit tmp überschrieben => es enthält nun den "gelöschten" Artikel nicht mehr.
Die folgende Methode listArtikel soll uns in der Konsole eine Tabelle ausgeben mit ein paar Informationen über eingetragene Produkte:
public void listArtikel()
{
System.out.println("|Artikel Nr| ArtikelTyp | Beschreibung | Anzahl auf Lager | Zusatzinfo |");
System.out.println("+----------+------------+---------------------------------------+-------------------+-------------------+");
for(int i = 0; i < artikelliste.length; i++)
{
System.out.println("| " + i + " " + artikelliste[ i ].toString());
}
}
Tja. Schaut ein bisschen kaputt aus. Funktioniert aber dennoch. Die toString-Methode kommt in der Klasse Artikel, sowie in allen Kind-Klassen von Artikel vor. Jedoch ist sie nicht immer gleich, (würde ja keinen Sinn machen) sie wurde immer individuell überschrieben. Wenn nun z. B. die toString-Methode bei einer CD aufgerufen wird, sieht man,
public String toString()
{
return "| " + "CD" + " " + super.toString();
}
dass in dieser Methode wiederum die Methode toString aufgerufen wird. Hier jedoch von ihrer Vaterklasse Medium:
public String toString()
{
if(altersFreigabe > -1)
{
return super.toString() + "| Altersfreigabe: " + altersFreigabe + " |";
} else {
return super.toString() + "| - keine - |";
}
}
Diese ruft ebenso die toString-Methode ihrer Vaterklasse (Artikel) auf . . .
public String toString(){
return "| " + artikelBeschreibung + " | " + availableArticles + " ";
}
Und aus diesen ganzen Kombinationen von toString aufrufen muss immer nur die toString-Methode eines Artikels angepasst werden, um einen individuellen Ausgabewert zu erzielen.
Die Methode buyArticle überprüft mit instanceof, ob man den Artikel kaufen darf oder ob er geliehen werden muss:
public void buyArticle(int articleNr )
{
if(artikelliste[articleNr] instanceof süßigkeit)
{
artikelliste[articleNr].decrementArticle();
} else {
System.out.println(artikelliste[articleNr].getArtikelName() + " darf nicht gekauft werden.");
}
}
Dann noch die Methode borrowAricle, die prüft wie die obige, mit instanceof ob der Artikel leihbar ist:
public void borrowArticle (int articleNr )
{
if(!(artikelliste[articleNr] instanceof süßigkeit))
{
if(artikelliste[articleNr].getAvailableArticles() > 0)
{
artikelliste[articleNr].decrementArticle();
} else {
System.out.println("Es sind zu wenige " + artikelliste[articleNr].getArtikelName() + " vorhanden.");
}
} else {
System.out.println(artikelliste[articleNr].getArtikelName() + " darf nicht geliehen werden.");
}
}
Und last but not least die Methode addArticle (in der für E erweiterten Form):
public void addArticle(Artikel article)
{
for(int i = 0; i < artikelliste.length; i++)
{
if(article.getArtikelNummer() == artikelliste[ i ].getArtikelNummer()){
System.out.println("Es ist schon ein Artikel mit der Artikelnummer "+ article.getArtikelNummer() + " vorhanden.");
return;
}
}
Artikel tmp[] = new Artikel [artikelliste.length + 1];
for(int i = 0; i < artikelliste.length; i++)
{
tmp[ i ] = artikelliste[ i ];
}
artikelliste = tmp;
artikelliste[artikelliste.length-1] = article;
}
Bei jedem gültigen Aufruf von addArticle wird das Array artikelliste um 1 erweitert. Der zuzufügende Artikel article wird nun an diese Position geschrieben. Es kann zudem kein Artikel mit gleicher Artikelnummer zum Array hinzugefügt werden, da bei einem solchen Fall das return das Programm aus dieser Methode katapultieren würde.
C:
Nun das Ganze noch in eine Paketform bringen . . . Man erstellt (wenn man mit eclipse arbeitet) in der linken Leiste einfach seine Pakete und schreibt seine Klassen dann direkt in diese oder fügt sie mit Drag & Drop nachträglich ein.

Man kann dies auch manuell machen:
package fh.videothek;
Dieser Code muss "ganz oben" eingegeben werden!
Mit diesem Code kann man auf die Klassen des importierten Packages zugreifen.
import fh.videothek.article.*;
Der Asterisk am Ende der Anweisung bewirkt, dass alle Klassen des Packages importiert werden. Wenn man aber nur eine Klasse aus diesem Package benötigt kann man - wie hier süßigkeit importieren:
import fh.videothek.article.süßigkeit;
D:
Nun noch eine Testsuite: Achtung In der Testsuite sind nicht alle gewünschten Anwendungen getestet. Diese müssen von euch individuell ergänzt werden ;)
import fh.videothek.*;
import fh.videothek.article.*;
public class Testsuite {
public static void main(String[] args) {
Videothek video = new Videothek();
CD article1 = new CD("Pink Floyd", 1,
"Pink Floyd, Another Brick in the Wall", 2);
video.addArticle(article1);
DVD article2 = new DVD("Dinofilm", 2,
"In Einem Land vor unserer Zeit ", 0, 2);
video.addArticle(article2);
süßigkeit article3 = new süßigkeit("Pink Floyd", 3,
"Kaugummi ", 20, "5Tage");
video.addArticle(article3);
video.listArtikel();
video.deleteArticle(4);
video.buyArticle(1);
video.buyArticle(0);
video.addArticle(article1);
video.listArtikel();
}
}
Und fertig ist der Käfer! Äh Programm :P
Viel Spaß!
Noch ein mal alles als in gezippter Form :P

Endlich mal jemand der sich mit wichtigen problemen zeitig beschäftigt! Dieser Eintrag ist ÜBERLEBENSNOTWENDIG... 10 von 5 möglichen Punkten!
Kommentar von Delics Andreas am 06. 04. 2008 um 19:59 UhrHallo zusammen,
diese Lösung ist natürlich schon nicht schlecht, wenn auch ein paar Sachen noch nicht ganz wie gefordert implementiert sind (z.B. die Tabelle soll auch "schön" ausschauen ...). Und Java Klassen mit "ü" oder "ß" zu benennen geht gar nich! (in der Praxis nimmt man fast immer englische Namen)
Nachdem es jetzt hier öffentlich eine Lösung gibt, muss ich natürlich jedem, der "seine" Codezeilen abgibt genau auf den Zahn fühlen, ob er den Code selbstgeschrieben und (zumindest) verstanden hat... aber das merkt man recht schnell. (früher wurden die Lösungen immer kopiert, online ist es natürlich noch komfortabler)
Herr Felber hat seine ersten 2 Haken aber wohl schon sicher ;)
Ich hoffe es entsteht hier jetzt nicht eine "ich lad mir den Code runter und geh schnell zur Praktikums-Abgabe" Kultur, v.a. weil die Konzepte Vererbung und Polymorphismus das absolute Grundwissen für OOSE mit Java sind. Wenn man das nicht versteht, wirds später sehr schwierig.
Zusammenfassung: @Herrn Felber: Lob, gute Lösung! @Rest: bitte nicht nur kopieren, sondern selber machen und verstehen, sonst verlieren sie irgendwann den Anschluss ... in der Prüfung können sie schließlich dann nichts runterladen.
Bis heute Nachmittag Viele Grüße Gregor Liebermann
Kommentar von Gregor Liebermann am 07. 04. 2008 um 13:36 UhrDann werde ich mal als Admin tätig: Die Praxis, die komplette Aufgabe online zu stellen halte ich auch für schwierig.
Aber vielleicht könnte man das so wie früher auch auf einzelne Ausschnitte begrenzen, die den Leuten, die sich mit den Aufgaben nicht ganz so leicht tun, weitergeholfen werden kann.
Kommentar von Florian Pichler am 07. 04. 2008 um 14:00 Uhr@Herrn Felber: Kleiner Nachtrag zum Code
Schauen Sie sich mal ihre deleteArticle() Methode noch genauer an. Man will eigentlich einen Artikel mit einer bestimmten ArtikelNummer löschen, nicht eine bestimmte Position im Array ... ebenso in der buyArticle() Methode.
(Über die Aufgabe hinaus wäre natürlich auch noch eine Methode interessant, die eine generische Artikelnummer erzeugt.)
Viele Grüße Gregor Liebermann
Kommentar von Gregor Liebermann am 07. 04. 2008 um 14:07 Uhr@Herrn Pichler: Klar, als Hilfe ist es sehr interresant, habe ich auch nichts dagegen. Wichtig ist mir nur, dass jeder auch versteht, was der Code eigentlich macht und warum es so oder so implementiert ist. Aber ansonsten ist gegen eine Online Hilfe (auch noch so eine Gute - Herr Felber erklärt ja die einzelnen Schritte top) nichts einzuwenden ... Solange ich nicht 40 mal das genau gleiche höre ;)
Kommentar von Gregor Liebermann am 07. 04. 2008 um 14:13 UhrSooooo Aufgrund der Verbesserungsvorschläge gibt es nun die überarbeiteten Versionen der Methoden deleteArticle, borrowArticle und buyArticle:
//edit: Leerzeichen für korrekte Darstellung hinzugefügt
Kommentar von Dominik Felber am 07. 04. 2008 um 15:29 UhrHallo Herr Felber,
leider muss ich nochmals an Ihrer Lösung rummeckern:
zum Beispiel ist in der delete Methode die Zeile "if(artikelliste.getArtikelNummer() == articleNr)" nicht ganz richtig.
Sie müssen die Methode getArtikelNummer() nicht auf der Liste implementieren sondern auf dem Artikel Objekt selbst (die Nummer müssen sie so behandeln wie einen Namen oder die Beschreibung) Bei Ihrer Implementierung würde ja für jeden Artikel in der Liste die gleiche Nummer zurückgegeben werden.
Korrekt müsste die Zeile ungefähr so aussehen:
Ich hoffe ich konnte Ihnen weiter helfen ...
@alle: Bei Fragen können Sie mich natürlich auch gerne anmailen.
Kommentar von Gregor Liebermann am 08. 04. 2008 um 13:19 Uhr@ Herrn Liebermann Ich sehe keinen Unterschied zwischen Ihrer Version und meiner.
AAAAAAber
das Problem liegt nicht an meinem/Ihren Code sondern dass aus [ i ] => der Text kursiv wird :P Sie sehen es ja an ihrer "korrekten" Zeile ;)
In Zukunft sollte ich lieber ein anderes Zeichen für die Zählvariable verwenden oder die zusätzlichen Leerzeichen bei der hier geposteten Version nicht vergessen. :D
Kommentar von Dominik Felber am 08. 04. 2008 um 14:54 UhrAhhhhhhhhhhh, verstehe! Sorry für die Rüge, dann ist ja alles richtig :)
Kommentar von Gregor Liebermann am 08. 04. 2008 um 17:44 UhrKleiner Nachtrag: Gestern wurde ich mehrmals gefragt, wie man denn eine Tabelle "schöner" formatieren kann... Schauen Sie sich hierzu mal genauer die String-Methoden "length()" und "substring(int a, int b)" an. Damit kann man ganz nette Sachen machen (in Kombination mit Schleifen ...)
Viel Spaß beim Tüfteln.
Kommentar von Gregor Liebermann am 08. 04. 2008 um 18:07 UhrSicher, man sollte schon zumindestens verstehen haben, worum es hier geht und deshalb es am Besten selbst programmieren. Allerdings sehe ich nicht warum man es unterbinden sollte, dass hier die Aufgabe in den Lösungsschritten on gestellt wird.
Immerhin wird die Aufgabe auch im Praktikum genau besprochen und gelöst. Anschliessend gibt es meist ne Mail mit der Lösung. Daher muss man so oder so schauen, ob der Student den Inhalt verstanden hat oder einfach nur copy&paste;gemacht hat.
Kommentar von Mark Welch am 09. 04. 2008 um 17:18 UhrServus,
Zum Copy&Paste;-Verfahren kann ich nur sagen, dass ich es im letzten Semester deutlich überstrapaziert habe. Das Ende der Geschichte war, dass ich drei Wochen vor der Prüfung keinen Strich coden konnte und komplett von vorne angefangen hab. Ist also nicht grad ratsam. Trotzdem finde ich, dass ein paar Schubser in die richtige Richtung sehr hilfreich sind und bin dafür weiterhin "Lösungsvorschläge" zu veröffentlichen.(Auch wenn ich meistens keine Ahnung hab was du da eigentlich schreibst lieber Dominik. Ich bin schon froh wenn ich meinen eigenen Code verstehe.)
Kommentar von Kaindl Manuela am 09. 04. 2008 um 17:49 Uhrich finde es auch gut, dass hier die einzelnen schritte nochmals erklärt werden, ab und zu häng ich einfach dumm an nem break oder sonstwas fest und das kostet einfach unendlich zeit, bis man den kleinen aber wichtigen fehler dann mal entdeckt hat.
desweiteren gibts ab und zu einfach lösungsvorschläge mit methoden die man eventuell noch nie gesehen hat und die einem bei besonderen problemen ziemlich weiterhelfen :)
Kommentar von Jakob Nicklbauer am 14. 04. 2008 um 15:20 Uhr