nihilfire: Vererbung

Hallo!
Habe die Aufgabe bekommen eine Unterklasse Schieberegister zu erstellen, welche Eigenschaften von einer Oberklasse Register erbt.
Der Konstruktor der Klasse Schieberegister bekommt ein Array mit den Registereinträgen z.B. {1,0,1,0,1,0} übergeben und soll prüfen, ob die einträge im Register "0" oder "1" sind. Wenn das der fall ist wir das Register gespeichert, wenn nicht soll ein Register derselben Länge wie das übergebene Array erzeugt und mit Nullen vorbesetzt werden. Dabei soll der Konstruktor der Oberklasse benutzt werden.

Wie kann man das realisieren?

Konstruktor der Klasse Register:

public class Register {

private short[] feld;
  private short index;

Register(short laenge){
    feld = new short[laenge];
    for (index = 0; index < feld.length; index++){
   feld[index] = 0;
    }
  }
}

Konstruktor der Klasse Schieberegister:

public class Schieberegister extends Register {

private short[] speicherRegister;
  private boolean anfErr = false;

Schieberegister(short[] speicherRegister){
   for (int i = 0; i < speicherRegister.length; i++){
      if(!(speicherRegister[i] == 0 || speicherRegister[i] == 1)){
         anfErr = true;
      }
      else{
         this.speicherRegister = speicherRegister;
      }
   }
  }
}

  1. Hi !

    1.) Was macht der Konstruktor der super-Klasse in diesem Beispiel ?
    2.) In wieweit paßt das, was er macht, zu Deinem Problem ?

    Gruß

    Hans

    1. Hi !

      1.) Was macht der Konstruktor der super-Klasse in diesem Beispiel ?

      Er setzt die Werte der Registers mit der länge "laenge" auf "0"

      2.) In wieweit paßt das, was er macht, zu Deinem Problem ?

      Wenn das übergebene Register an einer Stelle nicht "0" oder "1" ist soll der Konstruktor der Oberkalsse aufgerufen werden, der dann alle Einträge mit "0" vorbesetzt.

      also mit "super(laenge);" denke ich, aber wo und wie, weiß ich nicht...

      Gruß, nihilfire

      1. moin nihilfire :)

        ich würde deiner Klasse Schieberegister noch zwei Methoden spendieren:
        Die erste nenne ich mal spontan "prüfeInhalt()" mit einem Rückgabewert des Typs boolean.
        In dieser Mehtode durchläufst du das Array des Schieberegisters (wie man das macht, siehst du schon im Konstruktor von "Register". Was dann noch fehlt ist eine Überprüfung ob der Inhalt 0 oder 1 ist. Weicht der Wert an irgend einer Stelle davon ab, wird false zurück geliefert ansonsten kann am Ende der Schleife ein true zurück gegeben werden.

        Falls der Aufruf deiner Methode false zurück gibt, rufst du die zweite Methode auf (die ich spontan "neuesRegister()" nenne). In dieser Mehtode rufst du ganz banal den Kostruktor der Klasse Register auf.

        liebe Grüße aus Berlin
        lina-

        --
        Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
        1. moin nihilfire :)

          ich würde deiner Klasse Schieberegister noch zwei Methoden spendieren:
          Die erste nenne ich mal spontan "prüfeInhalt()" mit einem Rückgabewert des Typs boolean.
          In dieser Mehtode durchläufst du das Array des Schieberegisters (wie man das macht, siehst du schon im Konstruktor von "Register". Was dann noch fehlt ist eine Überprüfung ob der Inhalt 0 oder 1 ist. Weicht der Wert an irgend einer Stelle davon ab, wird false zurück geliefert ansonsten kann am Ende der Schleife ein true zurück gegeben werden.

          Falls der Aufruf deiner Methode false zurück gibt, rufst du die zweite Methode auf (die ich spontan "neuesRegister()" nenne). In dieser Mehtode rufst du ganz banal den Kostruktor der Klasse Register auf.

          liebe Grüße aus Berlin
          lina-

          danke für den Tip aber ich soll mich ja an die Aufgabenstellung halten und die Überprüfung im Konstruktor der Unterkalsse machen...

          Aufgebenstellung:
          Der Konstruktor soll ein Array mit short-Einträgen als Parameter übergeben bekommen. Er soll prüfen, ob alle diese Einträge 0 oder 1 sind und (falls das der Fall ist) sie bei der Erzeugunug der neuen Registers als Anfangswerte benutzen. Ist das nicht der Fall, so soll ein Register mit derselben Länge wie der Übergebene Array erzeugt und mit Nullen vorbesetzt werden. Dabei soll der Konstruktor der Oberklasse benutzt werden.

          ohne den letzten Satz zu beachten sieht meine Lösung so aus:

          Schieberegister(short[] speicherRegister){
            for (int i = 0; i < speicherRegister.length; i++){
           if(!(speicherRegister[i] == 0 || speicherRegister[i] == 1)){
             anfErr = true;
           }
           else{
             this.speicherRegister = speicherRegister;
           }
            }
            if(anfErr){
              for (int j = 0; j < speicherRegister.length; j++){
                speicherRegister[j] = 0;
              }
            }
          }

          Gruß, nihilfire

          1. moin nihilfire :)

            danke für den Tip aber ich soll mich ja an die Aufgabenstellung halten und

            die Überprüfung im Konstruktor der Unterkalsse machen...

            das habe ich glatt überlesen.

            ohne den letzten Satz zu beachten sieht meine Lösung so aus:[...]

            Das könnte funktionieren - ist aber nicht sehr elegant gelöst.

            Du benutzt ja schon eine boolean-Variable um die Richtigkeit der Einträge zu benutzen. Wieso also weist du den speicherRegister in jedem Schleifendurchgang neu zu?

            Ich würde den Ansatz mit dem boolean-Wert weiterverfolgen:
            1. sobald anfErr true ist, kann die Schleife abgebrochen werden (break)
            2. die Zuweisung des Arrays in der Schleife (jedesmal) ist Schwachsinnig
            3. Diese Zuweisung lieber erst als else-Zweig für die Auswertung von anfErr

            liebe Grüße aus Berlin
            lina-

            --
            Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
            1. Hab's jetzt so gemacht:

              Schieberegister(short[] speicherRegister){
                super(calcLength(speicherRegister));
                anfErr  = calcLength(speicherRegister) < speicherRegister.length;
                if (anfErr) {
                  this.speicherRegister = speicherRegister;
                }
                else{
                  this.speicherRegister = super.getFeld();
                }
              }

              static short calcLength( short[] speicherRegister) {
                boolean ok = true;
                for (int i = 0; i < speicherRegister.length; i++){
                  if(!(speicherRegister[i] == 0 || speicherRegister[i] == 1)) {
                    ok = false;
                    break;
                  }
                }
                return (short) ( ok ? 0 : speicherRegister.length);
              }

              Gruß, nihilfire

        2. Hallo lina,

          Falls der Aufruf deiner Methode false zurück gibt, rufst du die zweite Methode auf (die ich spontan "neuesRegister()" nenne). In dieser Mehtode rufst du ganz banal den Kostruktor der Klasse Register auf.

          Du kannst Konstruktoren von Elternklassen nicht einfach irgendwo und irgendwann aufrufen sondern nur von Konstruktoren aus und auch da nur als erste Anweisung. Für die Gründe für diese Einschränkung verweise ich mal an die Java Language Specification bzw. Java Virtual Machine Specification, in denen genau beschrieben ist, wie so eine Instanzierung abläuft.

          Grüße

          Daniel

  2. Hallo nihilfire,

    Also ersteinmal ist es so, dass Du immer ein Konstruktor der Elternklasse aufgerufen wird. Wenn diese wie in Deinem fall keinen Konstruktor ohne Parameter hat, musst Du explizit einen mit Parametern aufrufen.

    Da die Elternklasse bereits ein Array für die Daten enthält, sollte man auch dieses verwenden. Das Problem ist, dass dieses als private deklariert ist, Du da also keine Daten reichnschreiben kannst. Darin würde ich einen Designfehler sehen, entweder muss das Array als protected deklariert werden oder es sollte eine Methode existieren, die dir das schreiben des Arrays erlaubt.

    Beispiel
    class Register {

    private short[] feld;
       private short index;

    Register(short laenge){
         feld = new short[laenge];
         // Arrays mit Zahlen werden immer mit 0 initialisiert, das explizit zu tun, kann man sich also schenken;
       }

    protected short[] getFeld() {
         return feld;
       }

    }

    class Schieberegister extends Register {

    Schieberegister(short[] speicherRegister){
         super(speicherRegister.length);
         for (int i = 0; i < speicherRegister.length; i++) {
           if (speicherRegister[i] != 0 && speicherRegister[i] != 1) {
             return;
           }
         }
         System.arraycopy(speicherRegister, 0, getFeld(), 0, speicherRegister.length);
       }
    }

    Grüße

    Daniel