Aufgabe zu Unterklassen, Vererbung

JavaIsTheBest

Bekanntes Mitglied
Hallo,
ich habe folgende Aufgabe, bei der ich im Moment nicht weiterkomme. Ich wäre über ein paar Ratschläge dankbar.
Java:
// Klasse: Konto.
class Account {
  // Private Klassenvariable:
  // Naechste zu vergebende Kontonummer.
  private static int nextNumber = 1;

  // Private Objektvariablen:
  private final int number = nextNumber++;
                // Kontonummer (unveraenderlich).
  private String holder;    // Kontoinhaber.
  private int balance = 0;    // Kontostand.

  // Oeffentliche Konstruktoren: Konto mit Inhaber h, ggf.
  // Anfangsbetrag b und eindeutiger Nummer konstruieren.
  public Account (String h) {
    holder = h;
  }
  public Account (String h, int b) {
    this(h);            // Den anderen Konstruktor aufrufen.
    balance = b;
  }

  // Oeffentliche Objektmethoden:
  // Kontonummer/-inhaber/-stand abfragen.
  public int number () { return number; }
  public String holder () { return holder; }
  public int balance () { return balance; }

  // Oeffentliche Objektmethoden:
  // Betrag amount einzahlen/abheben/überweisen.
  public void deposit (int amount) {
    balance += amount;
  }
  public void withdraw (int amount) {
    balance -= amount;
  }
  public void transfer (int amount, Account that) {
    withdraw(amount);
    that.deposit(amount);
  }

  // Oeffentliche Klassenmethode:
  // Anzahl bereits erzeugter Konten abfragen.
  public static int numberOfAccounts () { return nextNumber - 1; }
}
Java:
// Unterklasse von Account: Limitiertes Konto.
class LimitedAccount extends Account {
  // Zusaetzliche Objektvariable:
  private int limit;        // Kreditlinie in Cent.

  // Konstruktoren:
  // Limitiertes Konto mit Inhaber h, ggf. Anfangsbetrag b,
  // Kreditlinie l und eindeutiger Nummer konstruieren.
  public LimitedAccount (String h, int b, int l) {
    super(h, b); // Konstruktor der Oberklasse Account aufrufen,
         // um deren Objektvariablen zu initialisieren.
    limit = l;     // Zusaetzliche Objektvariable limit initialisieren.
  }
  public LimitedAccount (String h, int l) {
    // Entweder:        // Oder:
    super(h);            // this(h, 0, l);
    limit = l;            //
  }

  // Zusaetzliche Objektmethode: Kreditlinie abfragen.
  public int limit () { return limit; }

  // Hilfsmethode: Kann Betrag amount abgezogen werden,
  // ohne die Kreditlinie zu ueberschreiten?
  private boolean check (int amount) {
    if (balance() - amount >= -limit) return true;
    System.out.println("Unzulaessige Kontoueberziehung!");
    return false;
  }

  // Ueberschreiben geerbter Objektmethoden:
  // Betrag amount abheben/ueberweisen.
  public void withdraw (int amount) {
    if (check(amount)) {
      // Ueberschriebene Methode aufrufen.
      super.withdraw(amount);
    }
  }
  public void transfer (int amount, Account that) {
    if (check(amount)) {
      // Ueberschriebene Methode aufrufen.
      super.transfer(amount, that);
    }
  }
}
Java:
public class ChargedAccount extends Account {
    private int count;
    public int charge=10;
   
    public ChargedAccount(String holder){
        super(holder);
    }
    public ChargedAccount(String holder, int balance){
        super(holder,balance);
    }
    public void deposit (int amount) {
        super.deposit(amount);
        count++;
    }
    public void withdraw (int amount) {
        super.withdraw(amount);
        count++;
    }
    public void charge(){
        // ......
    }
   
   
   

}
 

Anhänge

  • 1.png
    1.png
    129 KB · Aufrufe: 38

JavaIsTheBest

Bekanntes Mitglied
Ich frage mich, ob mein bisheriger Code in der Klasse ChargedAccount richtig ist und ob ihr mir Hinweise zur Implementierung der Methode charge geben könnt.
Klasse Account und LimitedAccount waren gegeben.
 

Jardcore

Top Contributor
Da es eine Klassenvariable sein soll muss sie in der Form static "final" deklariert werden.
In welcher Einheit ist der Kontostand? Cent? :)

Java:
    private static final int CHARGE = 10;

    public void charge() {
        count = 0;
        balance -= CHARGE;
    }

EDIT: zur Begriffserklärung ohne static ist es eine Instanzvariable und ohne final könnte sie noch veränder werden. Mit static final beschreibt man in Java Konstanten.
 

Jardcore

Top Contributor
Java:
   public void charge(){
        withdraw(CHARGE * count);
        count = 0;
   }

Btw: du solltest deinem Lehrer mal sagen das Java Camel Case benutzt... das heißt withDraw(..);
Und Getter beginnen normalerweise auch mit einem get ... deswegen ja Getter XD

Muss gestehen hab das auch übersehen, dachte balance wurde public deklariert... aber das war ja der komische Getter^^

Edit:
Ich schätze mal die eigentliche Aufgabe ist hier zu verstehen wie was von wem warum auch immer irgendwas erbt und wie man trotzdem auch private Attribute zugreift. Und weniger die Aufgaben zu lösen^^
 

Meniskusschaden

Top Contributor
Btw: du solltest deinem Lehrer mal sagen das Java Camel Case benutzt... das heißt withDraw(..);
Und Getter beginnen normalerweise auch mit einem get ... deswegen ja Getter XD
Also withdraw würde ich auch komplett klein schreiben. Ist doch eigentlich kein zusammengesetztes Verb. Ausserdem ist withdraw meines Erachtens auch kein Setter (nehme an, du meintest nicht Getter), denn die Zuweisung erfolgt ja mit -=.
 

JavaIsTheBest

Bekanntes Mitglied
Der Compiler gibt eine Fehlermeldung aus, weil die linke Seite keine Variable ist, aber es muss doch beim Aufruf der Methode charge der Kontostand geändert werden.

Java:
public class ChargedAccount extends Account {
    private int count;
    private static int charge=10;
   
    public ChargedAccount(String holder){  // Konstruktor von der Oberklasse erben
        super(holder);
    }
    public ChargedAccount(String holder, int balance){
        super(holder,balance);
    }
    public void deposit (int amount) {  //Methoden von der Oberklasse überschreiben
        super.deposit(amount);
        count++;
    }
    public void withdraw (int amount) {
        super.withdraw(amount);
        count++;
    }
    public void charge(){
        super.balance()-=charge*count;
        count=0;
    }
}
 

Meniskusschaden

Top Contributor
super.balance() ist eine Methode. Der kannst du nichts zuweisen. Du musst sie mit den geeigneten Parametern aufrufen. Die Methode berechnet dann die Klassenvariable balance neu. Wie sie das berechnet, siehst du in der Klasse Account.
 

JavaIsTheBest

Bekanntes Mitglied
Die Methode balance hat keine Parameter und liefert nur den Kontostand zurück. Sonst macht die Methode nichts.
Deswegen, weiß ich immer noch nicht, was ch anders machen muss.
 

JavaIsTheBest

Bekanntes Mitglied
Ich weiß nicht, ob das so stimmt.

Java:
    public void charge(){
        super.withdraw(charge*count);
        count=0;
    }

Ich habe mr überlegt, für ein ChargedAccount müssen vom eigenen Konto bei einer Überweisung "charge*count Cent" abgezogen werden.
Mir stellt sich die Frage, hätte/sollte/musste ich lieber für diese Operation die transfer Methode verwenden?
 

Meniskusschaden

Top Contributor
Ich glaube, die charge-Methode ist so richtig.

Ich habe mr überlegt, für ein ChargedAccount müssen vom eigenen Konto bei einer Überweisung "charge*count Cent" abgezogen werden.
Mir stellt sich die Frage, hätte/sollte/musste ich lieber für diese Operation die transfer Methode verwenden?
Fragst du jetzt, ob du mit der transfer-Methode die Gebühren abbuchen sollst oder ob du damit die Überweisung abwickeln sollst? Bin mir nicht sicher, ob ich die Frage richtig verstanden habe.
Für eine gebührenpflichtige Überweisung fallen aber nicht "charge*count Cent" an, sondern nur "charge Cent". Aber eben nicht sofort, sondern erst sobald für das Konto die Gebührenberechnung mittels charge-Methode erfolgt. Das heisst, zum Gebühren abbuchen ist die transfer-Methode nicht gedacht, sondern um eine Überweisung von einem Konto auf ein anderes zu buchen.
 
Zuletzt bearbeitet:

Jardcore

Top Contributor
Will hier kurz anmerken, das ich mich mit der genauen Aufgabenstellung nicht beschäftigt habe.
Also ob CHARGE * count oder was auch immer. Wichtig ist nur wie du darauf zugreifen kannst und dafür sind ein paar Methoden im Account definiert. Welche Rechnung nun erforderlich ist, steht hoffentlich in der Aufgabenstellung :)
 

JavaIsTheBest

Bekanntes Mitglied
@Meniskusschaden
Die Gebühr für eine Überweisung beträgt 10 Cent. Wenn man 4 Überweisungen tätigt, dann beträgt die Gebühr 4*10=40 Cent.
Warum also nicht count*charge?
Oder könntest du, mir die Aufgabenstellung erklären? Ich weiß nicht, ob der Gedankengang so richtig ist.
 

Meniskusschaden

Top Contributor
Du hattest in Post #19 geschrieben, dass bei EINER Überweisung "count*charge Cent" abgezogen werden. Das wollte ich nur richtig stellen, denn bei EINER Überweisung sind es nur "charge Cent". In der Methode charge() sollen aber ALLE gebührenpflichtigen Buchungen belastet werden. Dort sind es deshalb "charge*count Cent".
 

JavaIsTheBest

Bekanntes Mitglied
Hier ist mein aktueller Code. Aus charge habe ich eine statische Variable gemacht.
Der Typecast hat aus irgendeinem Grund nicht geklappt.
Java:
public class ChargedAccount extends Account {
    private int count;
    private static int charge=10;
  
    public ChargedAccount(String holder){  // Konstruktor von der Oberklasse erben
        super(holder);
    }
    public ChargedAccount(String holder, int balance){
        super(holder,balance);
    }
    public void deposit (int amount) {  //Methoden von der Oberklasse überschreiben
        super.deposit(amount);
        count++;
    }
    public void withdraw (int amount) {
        super.withdraw(amount);
        count++;
    }
    public void charge(){
        super.withdraw(charge*count); //Von welchem Kontoinhaber?
        count=0;
    }
}
Java:
public class AccountTest {
    public static void main(String[] args){
        ChargedAccount charge=new ChargedAccount("Max",3000);
        LimitedAccount limit=new LimitedAccount("Kevin",1000);
      
        Account accountCharge=charge;
        Account accountLimit=limit;
      
        accountCharge.transfer(500, accountLimit);
        accountCharge.transfer(4000, accountLimit);
        accountLimit.transfer(100,accountCharge );
        accountLimit.transfer(7000,accountCharge );
      
         /* Wozu Typecast? Warum aus Account ein ChargedAccount machen?
            Warum ist es möglich aus Account ein ChargedAccount aber umgekehrt nicht?
          */
        (ChargedAccount) accountCharge.charge();
        System.out.println(accountLimit.balance());
        System.out.print(accountCharge.balance());
      
    }

}
 

Meniskusschaden

Top Contributor
Zur ersten Frage im Quelltext (/* Wozu Typecast? Warum aus Account ein ChargedAccount machen?):
Du hast accountCharge als Variable vom Typ Account deklariert. Man kann darin also ein Objekt vom Typ Account oder einer Unterklasse von Account speichern. Hier wären derzeit noch LimitedAccount und ChargedAccount möglich. Jetzt soll die Methode charge() für das Objekt aufgerufen werden. Der Compiler hat nun ein Problem, denn die Methode ist nur für die Klasse ChargedAccount definiert, er weiß zum Zeitpunkt der Übersetzung jedoch nicht, ob das Objekt wirklich von diesem Typen ist. Es könnte ja auch einem der beiden anderen Typen angehören und für die gibt es keine charge-Methode. Du weißt es aber besser und teilst dem Compiler deshalb durch den Typecast mit, dass es sich um ein ChargedAccount handelt.

Zur zweiten Frage im Quelltext (Warum ist es möglich aus Account ein ChargedAccount aber umgekehrt nicht?):
Umgekehrt ist es nicht nötig, denn ein Objekt vom Typen einer erweiterten Klasse ist gleichzeitig auch immer vom Typen der übergeordneten Klassen. Ein Hund ist auch ein Säugetier und auch ein Tier. Ein Tier muß kein Säugetier sein, sondern es ist vielleicht ein Fisch. Deshalb benötigt man für die eine Richtung einen Typecast und für die andere nicht.

Der Typecast hat aus irgendeinem Grund nicht geklappt.
Dein Code (ChargedAccount) accountCharge.charge(); versucht folgendes zu machen: Er ruft auf dem Objekt accountCharge die Methode charge() auf und wendet dann einen Typecast auf das von charge() zurückgelieferte Objekt an. Das ist falsch, denn zum Einen ist der Rückgabetyp von charge() void, so daß überhaupt kein Objekt zurückgeliefert wird, zum Anderen ist es ohnehin nicht das, was du erreichen möchtest. Du willst ja erst den Typecast durchführen und dann auf dem gecasteten Objekt die Methode charge() aufrufen.
 

Meniskusschaden

Top Contributor
Sieht gut aus. :)

Du kannst in der Test-Klasse noch zwei Zeilen und zwei Variablen einsparen, indem du für die beiden Account-Variablen direkt mit dem jeweiligen Unterklassen-Konstruktor das gewünschte Konto erzeugst. Der Umweg über die Variablen charge und limit ist nicht nötig.
 

Neue Themen


Oben