1.6 Musterklassenarbeit
Papierversion, ausdrucken und ohne weitere Hilfsmittel versuchen zu lösen.
Klassenarbeitsverwaltung für Schüler
Hinweis: Quellcode muss sauber formatiert und sinnvoll kommentiert sein!
1. Ausgeben aller Klassenarbeiten 10P
Erstellen Sie ein Struktogramm für die Methode ausgebenKlassenarbeiten(), die für alle vorhandenen Klassenarbeiten deren Methode ausgeben() aufruft.
Lösung
2. Methoden neueKlassenarbeit(..) 20P
Um die Noten neuer Klassenarbeiten zu speichern sind in der Klasse Schueler zwei Methoden vorgesehen. Es muss immer ein Fach angegeben werden. Erstellen Sie den Quelltext für:
2.1 neueKlassenarbeit(pFach:Text, pNote:FKZ) überprüft die Noteneingabe. Ausgabe im Fehlerfall: „Fehlerhafte Note“
Lösung
public void neueKlassenarbeit(String pFach, double pNote){
if (pFach==null || pFach=="" || pNote<1.0 || pNote>6.0){
System.out.println("Fehlerhafte Note!");
}else
dieKlassenarbeit.add(new Klassenarbeit(pFach,pNote));
}
}
import java.io.*;
public class Klassenarbeit{
private String aFach; //{nicht leer}
private double aNote; //{>=1.0;<=6.0}
public Klassenarbeit(String pFach, double pNote){
if (pFach==null || pFach=="" || pNote<1.0 || pNote>6.0){
aFach="Fehlerhafte Note";
System.out.println(aFach);
}
else{
aFach=pFach;
aNote=pNote;
}
}
public String getFach(){
return aFach;
}
public double getNote(){
return aNote;
}
public void ausgeben(){
System.out.printf("%-8s %2.1f\n",aFach,aNote);
}
public String rueckgebenDatensatz(){
return String.format("%s;%2.1f\n",aFach,aNote);
}
}
2.2 neueKlassenarbeit(pFach:Text, pMax:GZ, pPunkte:GZ) überprüft die Punkteingabe (0<=pPunkte<=pMax). Ausgabe im Fehlerfall: „Fehlerhafte Daten“.
Die Note soll auf eine Nachkommastelle gerundet gespeichert werden.
Tipp: note = 6-5*pPunkte/pMax
Lösung
public void neueKlassenarbeit(String pFach, int pMax, int pPunkte){
if (pFach==null || pFach=="" || pMax<=0 || pPunkte<0 || pPunkte > pMax){
System.out.println("Fehlerhafte Daten");
}else {
double n = ((int)((6-(5.0*pPunkte/pMax))*10+0.5))/10.0;
dieKlassenarbeit.add(new Klassenarbeit(pFach,n));
}
}
2.3 Um welche Art von Polymorphie handelt es sich dabei? Begründen Sie
und gehen dabei auf den Begriff Signatur ein.
Lösung
Es handelt sich um statische Polymorphie, Überladen von Operationen. Bereits zur Compilezeit kann entschieden werden welche der beiden Methoden verwendet werden sollen. Die Signatur ist der Name der Methode und die Liste der Parameterdatentypen, hier:
neueKlassenarbeit(Text,FKZ), neueKlassenarbeit(Text,GZ,GZ).
3. Datensätze aus Datei einlesen 10P
Die Datensätze werden mit der Methode Klassenarbeit.rueckgebenDatensatz() in einer CSV-Datei gespeichert.
Erstellen Sie den Quellcode für die Methode leseCSV(pFilename:Text) die die Datensätze aus einer CSV-Datei einliest und hinzu fügt.
Lösung
public void leseCSV(String pFilename) { // try-catch nicht im Struktogramm darstellbar
String zeile;
String[] attribute;
try { // versuchen wir mal folgenden Code aus zu führen
BufferedReader ein = new BufferedReader(new FileReader(pFilename));
while ((zeile = ein.readLine())!= null){ // solange Datensätze vorhanden
zeile=zeile.replace(',','.'); // damit Doubleparsen geht
attribute = zeile.split(";"); // zerlege
neueKlassenarbeit(attribute[0],Double.parseDouble(attribute[1]));
}
ein.close();
} catch (IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
System.out.println("IOException: " + e); // gib den Fehler auf der Konsole aus
}
}
4. Objektdiagramm zur Testmethode 10P
In der Klasse Schueler werden in einer Methode test() nebenstehende Programmzeilen ausgeführt. Erstellen Sie ein Objektdiagramm.
Lösung
neueKlassenarbeit("SAE",3.0);
neueKlassenarbeit("Deutsch",2);
neueKlassenarbeit("BWL",30,20);
5. Erweitern und modifizieren des Klassendiagramms 10P
Als Fachnoten gibt es nicht nur Klassenarbeiten sondern auch mündliche Noten.
Erweitern und modifizieren Sie das Klassendiagramm: Es gibt eine Oberklasse Noten und zwei Unterklassen Klassenarbeit und Muendlich.
Lösung
Zur Übung alles implementieren
Implementieren Sie die Klassen Schuler und Klassenarbeiten. Test-Methode:
public void test(){
System.out.println("\f");
neueKlassenarbeit("SAE",3.0);
neueKlassenarbeit("Deutsch",2);
neueKlassenarbeit("BWL",30,20);
neueKlassenarbeit("SAE",4);
neueKlassenarbeit("ITS",2.4);
ausgebenKlassenarbeiten();
ausgebenDurchschnitt("Deutsch");
ausgebenDurchschnitt("SAE");
ausgebenDurchschnitt("Englisch");
schreibeCSV("noten.txt");
leseCSV("noten.txt");
ausgebenKlassenarbeiten();
}
Lösung Schueler
import java.io.*;
import java.util.ArrayList;
public class Schueler{
private ArrayList<Klassenarbeit> dieKlassenarbeit = new ArrayList<Klassenarbeit>();
public void neueKlassenarbeit(String pFach, int pMax, int pPunkte){
if (pFach=="" || pMax<=0 || pPunkte<0 || pPunkte > pMax){
System.out.println("Fehlerhafte Daten");
}else {
double n = ((int)((6-(5.0*pPunkte/pMax))*10+0.5))/10.0;
dieKlassenarbeit.add(new Klassenarbeit(pFach,n));
}
}
public void neueKlassenarbeit(String pFach, double pNote){
if (pFach=="" || pNote<1.0 || pNote>6.0){
System.out.println("Fehlerhafte Note!");
}else
dieKlassenarbeit.add(new Klassenarbeit(pFach,pNote));
}
public void ausgebenKlassenarbeiten(){
int i=0;
while (i<dieKlassenarbeit.size()){
dieKlassenarbeit.get(i++).ausgeben();
}
}
public double durchschnitt(String pFach){
double sum=0;
int n=0;
int i=0;
while (i<dieKlassenarbeit.size()){
if(dieKlassenarbeit.get(i).getFach()==pFach){
sum += dieKlassenarbeit.get(i).getNote();
n++;
}
i++;
}
if (n>0)
return sum /n;
System.out.println("Keine "+pFach+"-Note vorhanden!");
return 0.0;
}
public void ausgebenDurchschnitt(String pFach){
System.out.printf("Durchschnitt im Fach %8s: %2.1f\n",pFach,durchschnitt(pFach));
}
public void schreibeCSV(String pFilename) { // try-catch nicht im Struktogramm darstellbar
int i=0;
try { // versuchen wir mal folgenden Code aus zu führen
BufferedWriter aus = new BufferedWriter(new FileWriter(pFilename));
while (i<dieKlassenarbeit.size()){
aus.write(dieKlassenarbeit.get(i).rueckgebenDatensatz());
i++;
}
aus.close();
} catch (IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
System.out.println("IOException: " + e); // gib den Fehler auf der Konsole aus
}
}
public void leseCSV(String pFilename) { // try-catch nicht im Struktogramm darstellbar
String zeile;
String[] attribute;
try { // versuchen wir mal folgenden Code aus zu führen
BufferedReader ein = new BufferedReader(new FileReader(pFilename));
while ((zeile = ein.readLine())!= null){ // solange Datensätze vorhanden
zeile=zeile.replace(',','.'); // damit Doubleparsen geht
attribute = zeile.split(";"); // zerlege
neueKlassenarbeit(attribute[0],Double.parseDouble(attribute[1]));
}
ein.close();
} catch (IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
System.out.println("IOException: " + e); // gib den Fehler auf der Konsole aus
}
}
public void test(){
System.out.println("\f");
neueKlassenarbeit("SAE",3.0);
neueKlassenarbeit("Deutsch",2);
neueKlassenarbeit("BWL",30,20);
neueKlassenarbeit("SAE",4);
neueKlassenarbeit("ITS",2.4);
ausgebenKlassenarbeiten();
ausgebenDurchschnitt("Deutsch");
ausgebenDurchschnitt("SAE");
ausgebenDurchschnitt("Englisch");
schreibeCSV("noten.txt");
leseCSV("noten.txt");
ausgebenKlassenarbeiten();
}
}
Implementieren Sie die Klassen nach der Modifizierung des Klassendiagramms: Schueler, Note, Klassenarbeit und Muendlich. Testmethode:
Hinweis zu „noten.txt“: Sollte eigentlich „noten.csv“ genannt werden, aber netterweise zeigt BlueJ txt-Dateien im ProjektBrowser an…
Ausgabe in der CSV-Datei der Testmethode:
SAE;3,0;K
Deutsch;2,0;K
BWL;2,7;K
SAE;4,0;M
ITS;2,4;K
public void test(){
System.out.println("\f");
neueNote('K',"SAE",3.0);
neueNote('K',"Deutsch",2);
neueNote("BWL",30,20);
neueNote('M',"SAE",4);
neueNote('K',"ITS",2.4);
ausgebenNoten();
ausgebenDurchschnitt("Deutsch");
ausgebenDurchschnitt("SAE");
ausgebenDurchschnitt("Englisch");
schreibeCSV("noten.txt");
leseCSV("noten.txt");
ausgebenNoten();
}
Lösung Note
import java.io.*;
public abstract class Note{
private String aFach; //{nicht leer}
private double aNote; //{>=1.0;<=6.0}
public Note(String pFach, double pNote){
if (pFach==null || pFach=="" || pNote<1.0 || pNote>6.0){
aFach="Fehlerhafte Note";
System.out.println(aFach);
}
else{
aFach=pFach;
aNote=pNote;
}
}
public String getFach(){
return aFach;
}
public double getNote(){
return aNote;
}
public abstract void ausgeben();
public abstract String rueckgebenDatensatz();
}
Lösung Klassenarbeit
import java.io.*;
public class Klassenarbeit extends Note{
public Klassenarbeit(String pFach, double pNote){
super(pFach,pNote);
}
public void ausgeben(){
System.out.printf("%-8s %2.1f Klassenarbeit\n",getFach(),getNote());
}
public String rueckgebenDatensatz(){
return String.format("%s;%2.1f;K\n",getFach(),getNote());
}
}
Lösung Schueler
import java.io.*;
import java.util.ArrayList;
public class Schueler{
private ArrayList<Note> dieNote = new ArrayList<Note>();
public void neueNote(char pArt,String pFach, double pNote){
if (pFach==null || pFach=="" || pNote<1.0 || pNote>6.0){
System.out.println("Fehlerhafte Note!");
}else{
switch (pArt){
case 'k':
case 'K':
dieNote.add(new Klassenarbeit(pFach,pNote));
break;
case 'm':
case 'M':
dieNote.add(new Muendlich(pFach,pNote));
break;
default:
System.out.println("Unbekannte Art!");
}
}
}
public void neueNote(String pFach, int pMax, int pPunkte){
if (pFach==null || pFach=="" || pMax<=0 || pPunkte<0 || pPunkte > pMax){
System.out.println("Fehlerhafte Daten");
}else {
double n = ((int)((6-(5.0*pPunkte/pMax))*10+0.5))/10.0;
dieNote.add(new Klassenarbeit(pFach,n));
}
}
public void ausgebenNoten(){
int i=0;
while (i<dieNote.size()){
dieNote.get(i++).ausgeben();
}
}
public double durchschnitt(String pFach){
double sum=0;
int n=0;
int i=0;
while (i<dieNote.size()){
if(dieNote.get(i).getFach()==pFach){
sum += dieNote.get(i).getNote();
n++;
}
i++;
}
if (n>0)
return sum /n;
System.out.println("Keine "+pFach+"-Note vorhanden!");
return 0.0;
}
public void ausgebenDurchschnitt(String pFach){
System.out.printf("Durchschnitt im Fach %8s: %2.1f\n",pFach,durchschnitt(pFach));
}
public void schreibeCSV(String pFilename) { // try-catch nicht im Struktogramm darstellbar
int i=0;
try { // versuchen wir mal folgenden Code aus zu führen
BufferedWriter aus = new BufferedWriter(new FileWriter(pFilename));
while (i<dieNote.size()){
aus.write(dieNote.get(i).rueckgebenDatensatz());
i++;
}
aus.close();
} catch (IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
System.out.println("IOException: " + e); // gib den Fehler auf der Konsole aus
}
}
public void leseCSV(String pFilename) { // try-catch nicht im Struktogramm darstellbar
String zeile;
String[] attribute;
try { // versuchen wir mal folgenden Code aus zu führen
BufferedReader ein = new BufferedReader(new FileReader(pFilename));
while ((zeile = ein.readLine())!= null){ // solange Datensätze vorhanden
zeile=zeile.replace(',','.'); // damit Doubleparsen geht
attribute = zeile.split(";"); // zerlege
neueNote(attribute[2].charAt(0),attribute[0],Double.parseDouble(attribute[1]));
}
ein.close();
} catch (IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
System.out.println("IOException: " + e); // gib den Fehler auf der Konsole aus
}
}
public void test(){
System.out.println("\f");
neueNote('K',"SAE",3.0);
neueNote('K',"Deutsch",2);
neueNote("BWL",30,20);
neueNote('M',"SAE",4);
neueNote('K',"ITS",2.4);
ausgebenNoten();
ausgebenDurchschnitt("Deutsch");
ausgebenDurchschnitt("SAE");
ausgebenDurchschnitt("Englisch");
schreibeCSV("noten.txt");
leseCSV("noten.txt");
ausgebenNoten();
}
}
Verletzung der OOP Designrichtlinien?
- Informationsexperte
Wer ist der Informationsexperte für diese Aufgabe? D.h. wer hat bzw. sollte die Information für diese Aktion haben, wer muss also angefragt werden? - Geringe Kopplung
Eine Klasse sollte möglichst wenig Verbindungen zu anderen Klassen aufweisen, so sind bei Änderungen weniger Klassen betroffen. - Hoher Zusammenhalt
Die Verantwortlichkeit einer Klasse sollte sich möglichst nur auf eine logische Aufgabe beziehen. - Erzeuger
Die Klasse ist für die Erzeugung neuer Objekte zuständig, welche die zu erzeugenden Objekte beinhaltet (Komposition, Aggregation), welche die Informationen zum Start des neuen Objekts enthält oder das zu erzeugende Objekt eng verwendet.
Die Zusicherungen werden in der Klasse Schueler und Klassenarbeit abgefragt. Ausserdem lassen sich Klassenarbeiten mit ungültigen Werten erzeugen.
Welche Designrichtline(n) wurde(n) verletzt? Nehmen Sie dazu Stellung.
Reparieren Sie das Design durch Zuhilfenahme von Exceptions.