Klassen und Objekte (2)

Brüche: Eine Klasse für sich

Mithilfe des Java-Editors wollen wir nun eine Klasse von gedachten Gegenständen untersuchen, die einerseits in Java noch nicht vorhanden, andererseits aber mit vorhandenen Strukturen relativ leicht zu modellieren ist: die Klasse der Bruchzahlen.

Wir starten also den Java-Editor, rufen auf UML - neue Klasse und geben unserer Klasse den Namen Bruch. Das Programm, das wir jetzt erstellen wollen, wird aus mehreren Klassen bestehen, also erstellen wir dafür zunächst einen eigenen Ordner.

Im Klassen-Editor klicken wir links auf das rote Quadrat Attribute.

Brüche sind Quotienten aus zwei ganzen Zahlen. Mithilfe der Angabe von Zähler und Nenner lässt sich ein Bruch also vollständig beschreiben. Wir erstellen mit Klick auf Neu zwei Attribute: zähler und nenner und stellen deren Typ jeweils auf int.
Den Zugriff belassen wir auf private, bei den Optionen lassen wir get- und set-Methode abgehakt.

Das bedeutet: Eine Klasse, die von außerhalb auf ein Objekt des Typs Bruch zugreifen will, kann die beiden Attribute weder direkt lesen noch verändern. Sie kann aber die jeweilige set-Methode aufrufen, denn diese ist public gesetzt. Alle vier Methoden hat der Java-Editor für uns auch schon fertig mit Code gefüllt.

Nach dem Klick auf Schließen können wir betrachten, wie der Java-Editor das Ergebnis in Programmcode umgesetzt hat. (Kommentare entfernt). Da die entsprechenden Haken im Dialog gesetzt waren, hat der Java-Editor jeweils eine get-und set-Methode für Zähler und Nenner erstellt. Die Attribute zähler und nenner selbst sind als private deklariert und können von außerhalb der Klasse Bruch nicht gesetzt oder abgefragt werden. Hierzu dienen die "Setter" und "Getter".


public class Bruch {

  private int zähler;
  private int nenner;

  public int getNenner() {
    return nenner;
  }
  public void setNenner(int nenner) {
    this.nenner = nenner;
  }
  public int getZähler() {
    return zähler;
  }
  public void setZähler(int zähler) {
    this.zähler = zähler;
  }
}


Andererseits wäre es praktisch, wenn man einen Bruch mit einem einzigen Befehl erzeugen könnte. Wir öffnen also noch über UML-Klasse bearbeiten wieder den UML-Editor und wählen diesmal die Registerkarte Methoden. Hier fügen wir eine Methode des Typs Konstruktor hinzu. Ein Konstruktor ist eine Methode, die einmalig bei der Erstellung eines Objekts aufgerufen wird. Wie die Klasse selbst, trägt sie automatisch den Namen Bruch.

Als formale Parameter geben wir den Namen zähler und den Typ int an und klicken auf Neu. Das wiederholen wir für den Nenner. Dann schließen wir den Dialog.


public class Bruch {

  private int zähler;
  private int nenner;

  public Bruch(int zähler, int nenner) {
    this.zähler = zähler;
    this.nenner = nenner;
  }

  public int getNenner() {
    return nenner;
  }
  public int getZähler() {
    return zähler;
  }
}


An dieser Stelle endet die Intelligenz des Editors. Der Inhalt der Methode kann nicht automatisch erstellt werden. Aber wir können uns die nötigen befehle von den beiden überflüssigen Settern für Zähler und Nenner klauen. Das Wort this bezieht sich auf die Klasse Bruch. Der Befehl this.zähler=zähler; bedeutet: Nimm den eigegebenen Parameter zähler und weise ihn als Wert dem Attribut zähler der Klasse Bruch zu. Dasselbe passier mit dem Nenner. Die Setter für Zähler und Nenner sind nun überflüssig, die Getter lassen wir drin.

Damit unsere Klasse auch gleich eine nützliche Information liefert, erstellen wir zum Schluss noch eine Funktion. Eine Funktion soll uns darüber informieren, ob der jeweilige Bruch ein echter Bruch ist (Echte Brüche sind kleiner als 1, ist der Betrag eines Bruches größer oder gleich 1, dann nennt man ihn einen unechten Bruch.

Wir klicken aber noch einmal auf UML-Klasse bearbeiten, und fügen die Methode istEcht des Typs boolean hinzu. Die Art stellen wir auf Funktion, den Zugriff auf public. Dann klicken wir auf Schließen.

Die Funktion echt() müssen wir selbst mit Leben füllen. Ergänzen Sie:

  public boolean echt() {
    return Math.abs(zähler) < Math.abs(nenner);
  } 

Jetzt wird gerechnet

Nun speichern Sie die Klasse Bruch ab und erzeugen im selben Ordner eine neue Klasse Bruchrechnung.


import java.util.*;

public class Bruchrechnung {

  public static void main(String[] args) {
    System.out.println("Bruchrechnung\n");
    Scanner Eingabe =new Scanner(System.in);

    System.out.print("Geben Sie den Zähler Ihres Bruches ein: ");
    int z = Eingabe.nextInt();
    System.out.print("Geben Sie den Nenner Ihres Bruches ein: ");
    int n = Eingabe.nextInt();
    Bruch b = new Bruch(z,n);

    System.out.println("Ihr Bruch lautet "+b.getZähler()+"/"+b.getNenner());
    if (b.istEcht()) {
      System.out.println("Ihr Bruch ist ein echter Bruch.");
    } else {
      System.out.println("Ihr Bruch ist ein unechter Bruch.");
    }
  }
}


Aufgaben:

  1. Erstellen Sie in der Klasse Bruch
    - eine Funktion public String getBruchstring(), die den Bruch als String z/n formatiert.
    - eine Funktion public double dezimalWert(), die den Bruch als Dezimalbruch ausgibt.
    - eine Funktion public boolean istPositiv(), die ermittelt, ob ein Bruch größer als 0 ist.
    und bauen Sie in die Klasse Bruchrechnung entsprechende Abfragen ein.
    Hinweis: Sie müssen zum Einbau zusätzlicher Funktionen nicht unbedingt den UML-Editor anwerfen,
    sondern können auch einfach in den Code schreiben.
  2. Erstellen Sie in der Klasse Bruch eine Prozedur kürzen(), so dass der Aufruf kürzen() innerhalb der Klasse Bruch bzw. b.kürzen() aus der Klasse Bruchrechnung heraus bewirkt, dass der Bruch intern gekürzt wird.