OOP Objektorientiert: Darstellung von Uhrzeiten im 24-Stunden-Format

Wayne139

Aktives Mitglied
Inhaltsverzeichnis
1. Meine Fragen
2. Aufgabe

3. Mein Code


1. Meine Fragen:

1) Ist mein Kopierkonstruktor weiter unten im Code richtig?
2) Die Methode writeTime() und toString() sind soweit identisch, ich verstehe aus der Aufgabenstellung nicht genau, was
da gemacht werden soll?
3) normalizeTime(), hat da jemand eine Idee wie man das richtig machen kann? Ich bekomme das nicht hin.
4) Hat jemand generell Verbesserungsvorschläge für meinen Code?

2. Aufgabe
12642
12643

3. Mein Code
Java:
//import utilities.TastaturEingabe;
class Time24{
  
  private int hour;
  private int minute;
  
  //Allgemeiner Konstruktor
  Time24(int hour, int minute){
    this.hour=hour;
    this.minute=minute;
  }
  
  //Standardkonstruktor
  Time24(){
    this(0,0);
  }
  
  //Kopierkonstruktor
  Time24(Time24 copy){
        this.hour = copy.getHour();
        this.minute = copy.getMinute();
  }
  
 
  void readTime(int hour,int minute){
    this.hour=hour;
    this.minute=minute;
  }
  
  
  void writeTime(){
    System.out.print(hour+":"+minute);
  }
  
  void addTime(int zahl){
    if(zahl>=0){
      minute += zahl;
    }
    else{
      minute = 0;
      minute += zahl;
    }
  }
  
  int getHour(){
    return hour;
  }
  
  void setHour(int hour){
    this.hour=hour;
  }
  
  int getMinute(){
    return minute;
  }
  
  void setMinute(int minute){
    this.minute=minute;
  }
  
  //String toString(){
    //return hour +hour":"+minute;
    //} 
  
 // private void normalizeTime(int hour, int minute){
   // minute += minute % 60;
     // hour += hour % 24;
    //}
  
  public static void main(String[] args){
    
    int h, m;
    
    Time24 sanfrancisco; 
    Time24 frankfurt;
    Time24 melbourne ;
    
    //h = TastaturEingabe.readInt("Stunden: ");
    h = 1;
    //m = TastaturEingabe.readInt("Minuten: ");
    m = 49;
    
    sanfrancisco = new Time24(h,m);
    frankfurt = new Time24(h+9,m);
    melbourne = new Time24(h+17,m);
    
    System.out.println(sanfrancisco.getHour()+":"+sanfrancisco.getMinute());
    System.out.println(frankfurt.getHour()+":"+frankfurt.getMinute());
    System.out.println(melbourne.getHour()+":"+melbourne.getMinute());
  }
}
 
1. Meine Fragen:
1) Ist mein Kopierkonstruktor weiter unten im Code richtig?
2) Die Methode writeTime() und toString() sind soweit identisch, ich verstehe aus der Aufgabenstellung nicht genau, was
da gemacht werden soll?
3) normalizeTime(), hat da jemand eine Idee wie man das richtig machen kann? Ich bekomme das nicht hin.
4) Hat jemand generell Verbesserungsvorschläge für meinen Code?

zu 1) Sah erst einmal gut aus. Der copy-Konstruktor übernimmt nur die Werte und das sah gut aus.
zu 2) writeTime() schreibst einfach die Daten ach System.out und toString() gibt nur einen String zurück und gibt nichts aus. (writeTime kann also toString nutzen um die Ausgabe zu erstellen)
zu 3) Was sind denn die Regeln? Kannst Du diese nicht einmal erst einmal so formulieren ohne an Java zu denken? Wann muss den was passieren? Wenn ich also z.B. Werte von 89 und 99 an den Konstruktor übergebe und normalize aufrufe - was sollte das das Ergebnis sein und wieso?
 
zu 1) Sah erst einmal gut aus. Der copy-Konstruktor übernimmt nur die Werte und das sah gut aus.
zu 2) writeTime() schreibst einfach die Daten ach System.out und toString() gibt nur einen String zurück und gibt nichts aus. (writeTime kann also toString nutzen um die Ausgabe zu erstellen)
zu 3) Was sind denn die Regeln? Kannst Du diese nicht einmal erst einmal so formulieren ohne an Java zu denken? Wann muss den was passieren? Wenn ich also z.B. Werte von 89 und 99 an den Konstruktor übergebe und normalize aufrufe - was sollte das das Ergebnis sein und wieso?
Zu 1) Vielen Dank

Zu 2)
Java:
  void writeTime(){
    System.out.print(hour+":"+minute);
  }

  String toString(){
    System.out.print(hour+":"+minute);
    }
Kann ich writeTime() auf toString() zugreifen lassen?
Bei toString bekomme ich die Fehlermeldung: Cannot reduce the visibility of the inherited method from java.lang.Object

Zu 3) Stunden(hours) sollen zwischen 0 und 23 liegen und Minuten(minute) zwischen 0 und 60 liegen. (Das könnte man mit hour>23 || hour<0 && minute>60 || minute<0 bewerkstelligen)

Wenn man 14:80 (wird zu 15:20) eingibt soll 80 modulo 60 = 20 Rest ausgerechnet werden und die 20 Rest sollen auf die Minuten hinzugerechnet werden und Stunden sollen um 1 erhöht werden. 27:15 (wird zu 0:30) 27 modulo 24 = 3 Rest. Der Rest wird auf die Stunden gerechnet. Wenn man 22:150 eingibt muss man dividieren. 150/60 ergibt 2,5 daraus folgt dass 2 Stunden und 30 Minuten (60*0,5) hinzugerechnet werden. (meine Idee wäre es minute += minute % 60 und hour += hour % 24 zu benutzen)

Hoffe du kannst mir weiterhelfen.
 
Kann ich writeTime() auf toString() zugreifen lassen?
Ja, wenn du toString berichtigst und einen String zurückgeben lässt, kannst du die Methode in writeTime aufrufen und den zurückgegebenen String ausgeben.

Bei toString bekomme ich die Fehlermeldung: Cannot reduce the visibility of the inherited method from java.lang.Object
toString ist in Object als public deklariert, du musst es also auch mindestens public machen - aktuell ist es, da ohne Angabe, package-private.
 
Zu 3) Stunden(hours) sollen zwischen 0 und 23 liegen und Minuten(minute) zwischen 0 und 60 liegen. (Das könnte man mit hour>23 || hour<0 && minute>60 || minute<0 bewerkstelligen)

Wenn man 14:80 (wird zu 15:20) eingibt soll 80 modulo 60 = 20 Rest ausgerechnet werden und die 20 Rest sollen auf die Minuten hinzugerechnet werden und Stunden sollen um 1 erhöht werden. 27:15 (wird zu 0:30) 27 modulo 24 = 3 Rest. Der Rest wird auf die Stunden gerechnet. Wenn man 22:150 eingibt muss man dividieren. 150/60 ergibt 2,5 daraus folgt dass 2 Stunden und 30 Minuten (60*0,5) hinzugerechnet werden. (meine Idee wäre es minute += minute % 60 und hour += hour % 24 zu benutzen)

Wenn du 80 Minuten hast, dann sind das 1h 20 min. Das ist soweit Richtig. Aber das bedeutet doch, dass der Minutenwert 20 ist - und nicht, dass die 20 zu dem bisherigen Minutenwert hinzurechnet.

Oder was man prinzipiell auch machen könnte: Die vollen Stunden abziehen, das würde also bedeuten, dass man eine Schleife hat und so lange Minute >=60 ist (Also auch >= und nicht nur >! Die Minuten gehen nur von 0 bis 59. nach der 59 kommt wieder die 0), rechnet man: 60 von Minute abziehen, 1 zu Stunde hinzu addieren.

Und bei Stunde ist dies natürlich ebenso. hour % 24 ist die nue Stunde. Also Du zählst nichts zu Stunde hinzu. Oder man kann das auch als Schleife überlegen: Solange Stunde >= 24 ist, ziehe 24 ab.

Das die Berechnung nicht stimmen kann, erkennst Du ja auch, wenn Du das einmal rechnest. Stunde 26 wäre ansonsten 28. (26 + 26%24 = 26 + 2) Da erkennt man auch, dass es keinen Sinn macht.

Kannst Du nun die Gleichungen aufschreiben?
a) Stunden anpassen (Änderung, die von den Minuten kommt)
b) Minuten anpassen
c) Stunden nun anpassen.
 
Ja, wenn du toString berichtigst und einen String zurückgeben lässt, kannst du die Methode in writeTime aufrufen und den zurückgegebenen String ausgeben.


toString ist in Object als public deklariert, du musst es also auch mindestens public machen - aktuell ist es, da ohne Angabe, package-private.

Java:
  //writeTime Methode ruft toString auf
  String writeTime(){
    return toString();
  }
  
//Gibt Stunden und Minuten aus
  public String toString(){
    return hour+":"+minute;
  }
Ist das so in Ordnung?
 
Wenn du 80 Minuten hast, dann sind das 1h 20 min. Das ist soweit Richtig. Aber das bedeutet doch, dass der Minutenwert 20 ist - und nicht, dass die 20 zu dem bisherigen Minutenwert hinzurechnet.

Oder was man prinzipiell auch machen könnte: Die vollen Stunden abziehen, das würde also bedeuten, dass man eine Schleife hat und so lange Minute >=60 ist (Also auch >= und nicht nur >! Die Minuten gehen nur von 0 bis 59. nach der 59 kommt wieder die 0), rechnet man: 60 von Minute abziehen, 1 zu Stunde hinzu addieren.

Und bei Stunde ist dies natürlich ebenso. hour % 24 ist die nue Stunde. Also Du zählst nichts zu Stunde hinzu. Oder man kann das auch als Schleife überlegen: Solange Stunde >= 24 ist, ziehe 24 ab.

Das die Berechnung nicht stimmen kann, erkennst Du ja auch, wenn Du das einmal rechnest. Stunde 26 wäre ansonsten 28. (26 + 26%24 = 26 + 2) Da erkennt man auch, dass es keinen Sinn macht.

Kannst Du nun die Gleichungen aufschreiben?
a) Stunden anpassen (Änderung, die von den Minuten kommt)
b) Minuten anpassen
c) Stunden nun anpassen.

Vielen Dank für deine Antwort, ich habe meinen Code nochmal überarbeitet und bin der Meinung, dass es jetzt funktioniert.
Das einzigste was mir noch auffällt ist, wenn bei Stunden oder Minuten, eine 0 - 9 steht dann wird auch nur z.B. 9:0 Uhr ausgegeben 09:00 Uhr wäre "schöner". Gibt es noch eine Möglichkeit die Null hinzuzufügen?


Java:
//import utilities.TastaturEingabe;
class Time24{
  
  private int hour;
  private int minute;
  
  //Allgemeiner Konstruktor
  Time24(int hour, int minute){
    this.hour=hour;
    this.minute=minute;
  }
  
  //Standardkonstruktor
  Time24(){
    this(0,0);
  }
  
  //Kopierkonstruktor
  Time24(Time24 copy){
        this.hour = copy.getHour();
        this.minute = copy.getMinute();
  }
  
  //readTime Methode
  void readTime(int hour,int minute){
    this.hour=hour;
    this.minute=minute;
  }
  
  //writeTime Methode ruft toString auf
  String writeTime(){
    return toString();
  }
  
  //Minuten werden hinzuaddiert
  void addTime(int zahl){
    if(zahl>=0){
      minute += zahl;
    }
    else{
      minute = 0;
      minute += zahl;
    }
  }
  
  //Stunde zurückgeben
  int getHour(){
    return hour;
  }
  
  //Stunde ändern
  void setHour(int hour){
    this.hour=hour;
  }
  
  //Minute zurückgeben
  int getMinute(){
    return minute;
  }
  
  //Minute ändern
  void setMinute(int minute){
    this.minute=minute;
  }
  
  //Gibt Stunden und Minuten aus
  public String toString(){
    return hour+":"+minute;
  } 
  
  //Prüft ob Stunden oder Minuten zu groß eingegeben wurde und korrigiert dieses.
  private void normalizeTime(){
    while(hour>=24 || hour<0 || minute>=60 || minute<0){
      if(hour>=24){
        hour -= 24;
      }
      if(minute>=60){
        minute -= 60;
        hour++;
      }
    }
  }
  
  public static void main(String[] args){
    
    int h, m;
    
    Time24 sanfrancisco; 
    Time24 frankfurt;
    Time24 melbourne;
    
    //h = TastaturEingabe.readInt("Stunden: ");
    h = 10;
    //m = TastaturEingabe.readInt("Minuten: ");
    m = 150;
    
    sanfrancisco = new Time24(h,m);
    frankfurt = new Time24(h+9,m);
    melbourne = new Time24(h+17,m);
    
    sanfrancisco.normalizeTime();
    frankfurt.normalizeTime();
    melbourne.normalizeTime();
    
    
    System.out.println(sanfrancisco.toString()+" Uhr");
    System.out.println(frankfurt.toString()+" Uhr");
    System.out.println(melbourne.toString()+" Uhr");
  }
}
 
Klar. Eine solche kannst Du Dir sogar selbst überlegen: für welche Werte brauchst Du denn eine führende 0? Kann man da ggf. mit if was machen...? Probiers ruhig mal, das übt.

Ich hab das in der toString Methode probiert. Zwei if-Anweisungen führen zu einem Fehler.
Weiß jemand hierzu eine Lösung?
Fehlermeldung: Unreachable code
Java:
  public String toString(){
    if(hour<=9 && hour>=0){
      return "0"+hour+":";
    } else{
      return hour+":";
    }
    if(minute<=9 && minute>=0){
      return "0"+minute+" Uhr";    
    } else{
      return minute+" Uhr";
    }  
  }
 
Du darfst nicht sofort aus der Methode zurückspringen, sondern erst am Ende. Führ mal zusätzliche Strings in der Methode ein:
Java:
public String toString() {
    String hourPart;
    if (hour <= 9 && hours >= 0) {
        hourPart = "0" + hour;
    } else {
        hourPart = "" + hour;
    }
    String minutePart;
    if ...
    return hourPart + ":" + minutePart;
}
 
Aso paar Tests, die Du mal machen solltest:
a) Stunden 23 Minuten 61 und dann normalize() -> Stimmt das Ergebnis?
b) Stunden 52 Minuten 30, normalize() -> Ergebnis prüfen
c) Stunden 1, Minuten 150, normalize() -> Ergebnis prüfen

Sind die Ergebnisse korrekt oder ist da noch etwas unstimmig?
 
Du darfst nicht sofort aus der Methode zurückspringen, sondern erst am Ende. Führ mal zusätzliche Strings in der Methode ein:
Java:
public String toString() {
    String hourPart;
    if (hour <= 9 && hours >= 0) {
        hourPart = "0" + hour;
    } else {
        hourPart = "" + hour;
    }
    String minutePart;
    if ...
    return hourPart + ":" + minutePart;
}
Vielen Dank. Deine Idee hat super funktioniert.
Meine toString habe ich entsprechend geändertz und diese macht genau das,was es tun soll
Java:
  public String toString() {
    String hourPart;
    if (hour <= 9 && hour >= 0) {
      hourPart = "0" + hour;
    } else {
      hourPart = "" + hour;
    }
    String minutePart;
    if(minute<=9 && minute>=0){
      minutePart = "0" + minute;
    } else {
      minutePart = "" + minute;
    }
      return hourPart + ":" + minutePart;
}
Aso paar Tests, die Du mal machen solltest:
a) Stunden 23 Minuten 61 und dann normalize() -> Stimmt das Ergebnis?
b) Stunden 52 Minuten 30, normalize() -> Ergebnis prüfen
c) Stunden 1, Minuten 150, normalize() -> Ergebnis prüfen

Sind die Ergebnisse korrekt oder ist da noch etwas unstimmig?
Sieht gut aus🙂
23 Stunden 61 Minuten = 00:01 Uhr 09:01 Uhr 17:01 Uhr

52 Stunden 30 Minuten = 13:30 Uhr 21:30 Uhr

01 Stunde 150 Minuten= 03:30 Uhr 12:30 Uhr 20:30 Uhr

Dank euch bin ich mit meinem Programm fertig, vielen Dank.
Mein fertiger Code:
Java:
//import utilities.TastaturEingabe;
class Time24{
 
  private int hour;
  private int minute;
 
  //Allgemeiner Konstruktor
  Time24(int hour, int minute){
    this.hour=hour;
    this.minute=minute;
  }
 
  //Standardkonstruktor
  Time24(){
    this(0,0);
  }
 
  //Kopierkonstruktor
  Time24(Time24 copy){
        this.hour = copy.getHour();
        this.minute = copy.getMinute();
  }
 
  //readTime Methode
  void readTime(int hour,int minute){
    this.hour=hour;
    this.minute=minute;
  }
 
  //writeTime Methode ruft toString auf
  void writeTime(){
    System.out.println(toString());
  }
 
  //Minuten werden hinzuaddiert
  void addTime(int zahl){
    if(zahl>=0){
      minute += zahl;
    }
    else{
      minute = 0;
      minute += zahl;
    }
  }
 
  //Stunde zurückgeben
  int getHour(){
    return hour;
  }
 
  //Stunde ändern
  void setHour(int hour){
    this.hour=hour;
  }
 
  //Minute zurückgeben
  int getMinute(){
    return minute;
  }
 
  //Minute ändern
  void setMinute(int minute){
    this.minute=minute;
  }
 
  //Gibt Stunden und Minuten aus ohne if ist ok dann nur return stunde+":"+minute;
  public String toString() {
    String hourPart;
    if (hour <= 9 && hour >= 0) {
      hourPart = "0" + hour;
    } else {
      hourPart = "" + hour;
    }
    String minutePart;
    if(minute<=9 && minute>=0){
      minutePart = "0" + minute;
    } else {
      minutePart = "" + minute;
    }
      return hourPart + ":" + minutePart;
}


 
  //Prüft ob Stunden oder Minuten zu groß eingegeben wurde und korrigiert dieses.
  private void normalizeTime(){
    while(hour>=24 || hour<0 || minute>=60 || minute<0){
      if(hour>=24){
        hour -= 24;
      }
      if(minute>=60){
        minute -= 60;
        hour++;
      }
    }
  }
 
  public static void main(String[] args){
    
    int h, m;
    
    Time24 sanfrancisco;
    Time24 frankfurt;
    Time24 melbourne;
    
    //h = TastaturEingabe.readInt("Stunden: ");
    h = 1;
    //m = TastaturEingabe.readInt("Minuten: ");
    m = 1;
    
    sanfrancisco = new Time24(h,m);
    frankfurt = new Time24(h+9,m);
    melbourne = new Time24(h+17,m);
    
    sanfrancisco.normalizeTime();
    frankfurt.normalizeTime();
    melbourne.normalizeTime();
    
    System.out.println(sanfrancisco.toString()+" Uhr");
    System.out.println(frankfurt.toString()+" Uhr");
    System.out.println(melbourne.toString()+" Uhr");
  }
}
 
Meine toString habe ich entsprechend geändertz und diese macht genau das,was es tun soll
Und wenn wir schon dabei sind, dann verbessern wir das Ganze gleich noch 🙂

Wenn Du Dir die Methode ansiehst, stellst Du fest, dass da zweimal genau das gleiche passiert: eine Zahl wird formatiert, so dass ihr eine 0 vorangestellt wird, sofern sie einstellig ist.

Doppelter Code ist etwas, das man nicht will: man löst damit ein und dasselbe Problem mehrfach. Das ist schlecht, weil es den Wartungsaufwand erhöht: Du musst mehr lesen, Du musst an mehreren Stellen etwas ändern, Du baust leichter Fehler ein usw.

Statt den Spaß zweimal in toString() zu lösen, überlegt man sich, dass man in toString() zweimal eine Zahl "auf zwei Stellen" formatieren will. Die Formatierung einer Zahl gliedert man aus:
Code:
private String twoDigits(int x) {
    if (x >= 0 && x <= 9) {
        return "0" + x;
    } else {
        return "" + x;
    }
}
Mit dem ternären Operator ließe sich das noch kürzer schreiben, aber lassen wir es mal so.

Damit kann man in toString schreiben:
Java:
public String toString() {
    return twoDigits(hour) + ":" + twoDigits(minute);
}

Das Ganze sollte nur der Übung dienen. Mit Bordmitteln (also ohne eigene Methoden) könnte das einfach so aussehen:
Java:
public String toString() {
    return String.format("%02d:%02d", hour, minute);
}

Die normalizeTime-Methode könnte man noch optimieren (s. Kommentar #5 von @JustNobody). Wenn Du Lust hast, kannst Du Dich ja daran noch versuchen 🙂
 

Zurück
Oben