Vererbung Kurze Frage bezüglich Methodenvererbung

Schwupsi

Aktives Mitglied
Hi Leute! Folgendes (kleines) Problem. Es soll ein kleines Steuerberechnungsprogramm geschrieben werden. Ich werde nicht weiter ins Detail gehen. Die Klasse "Bauer" erbt von "Einwohner". Die Klasse "Leibeigener" von "Bauer".

Einwohner<-----Bauer<-----Leibeigener.

In der Klasse Einwohner ist eine Methode getSteuer() die die Steuern des Einkommens berechnet. Andere Klassen wie "König" und "Adel" haben Sonderregelungen, weshalb ich lokal nochmal spezialisierte getSteuer() Methoden implementiert habe. Die Klasse "Bauer" hat keine Sonderregelung und kann die Standard-Methode getSteuer() von der Klasse "Einwohner" erben, die sieht wie folgt aus:

Java:
   public int getSteuer(){
       int steuer;
  
       steuer = (getZuVersteuerndesEinkommen()/100)*10;
       if(steuer>1){
     
       return steuer;
       }
       return 1;
     }


In einer Testklasse wird der Klasse Bauer in einem Objekt ein Einkommen von 20 zugewiesen, wodurch die Steuer also 2 sein müsste. Bei allen anderen Klassen funktioniert es, nur bei "Bauer" kommt immer 1 raus. Also ignoriert Eclipse die if-Abfrage und springt direkt in "return 1;". Weil würde Eclipse die if-Abfrage machen, würde es sehen, dass 2 > 1 ist und "steuer" zurückgeben und nicht 1. Liege ich richtig? Hat es was damit zu tun, dass "Bauer" Sub- und Superklasse gleichzeitig ist? Habe auch schon probiert die Methode direkt einzufügen in die Klasse "Bauer", gibt mir auch 1 zurück.


Gruß und hoffe auf eine hilfreiche Antwort :)
 

Tarrew

Top Contributor
Deine "getZuVersteuerndesEinkommen()" Methode gibt wohl ein int zurück.

Die Berechnung in der Klammer ergibt also 0. Und 0*10 = 0;
Du könntest den Rückgabewert auf double casten und am Ende dann wieder auf ein int casten, dann sollte es passen.

Java:
steuer = (int) (((double)getZuVersteuerndesEinkommen()/100)*10);

Mit den 2 casts sieht das natürlich nicht so toll aus. Warum rechnest du nicht direkt mit doubles?
 

Schwupsi

Aktives Mitglied
Deine "getZuVersteuerndesEinkommen()" Methode gibt wohl ein int zurück.

Die Berechnung in der Klammer ergibt also 0. Und 0*10 = 0;
Du könntest den Rückgabewert auf double casten und am Ende dann wieder auf ein int casten, dann sollte es passen.

Java:
steuer = (int) (((double)getZuVersteuerndesEinkommen()/100)*10);

Mit den 2 casts sieht das natürlich nicht so toll aus. Warum rechnest du nicht direkt mit doubles?


Tatsächlich, nun ist die Ausgabe richtig. Da mache ich mir unnötig einen Kopf und denke nicht an das simpelste. Vielen Dank!!
 

stg

Top Contributor
Statt hin-und-her-casterei hätte man ja auch einfach durch 10 Teilen können, anstatt erst durch 100 und hinterher wieder mit 10 zu multiplizieren :-O
 

Thallius

Top Contributor
Mit den 2 casts sieht das natürlich nicht so toll aus. Warum rechnest du nicht direkt mit doubles?

Bitte nicht solche vollkommen verherenden Tipps geben. Alles was mit Preisen/Geld/Währung zu tun hat muss defintitiv auf den Cent genau ausgerechnet werden. Dafür ist Rechnen mit double viel zu ungenau!

Also bitte NIEMALS Währungen in float oder double berechnen.

In dem Fall des TO wäre ein einfaches Teilen durch 10 die einzig richtige Methode gewesen, auch wenn er es jetzt bestimmt mit dem Cast auf double komplett falsch gemacht hat.

Genau richtig wäre übrigens wenn er auch noch richitig rundet. also

(getZuVersteuerndesEinkommen()+5)/10;

Gruß

Claus
 

Schwupsi

Aktives Mitglied
Erstmal danke für eure Hilfe! Top! *Daumenhoch*

Ein anderes Programm macht mir folgende Probleme:

1. Frage

a) Die Zinssätze für Sparbuch und Bausparkonto sowie der Überziehungszins des Girokontos sollen für alle Instanzen der jeweiligen Klasse gleich sein (d.h. z.B. werden alle Sparbücher gleich verzinst).

Habe gegoogelt und gefunden, dass die Variable "Zins"(Sparbuch&Bausparkonto) oder "Überziehungszins"(Girokonto)für alle erzeugten Objekte der jeweiligen Klasse gilt, also eine Instanzvariable ist und somit STATIC sein muss, richtig? Oder doch lieber als Interface?

2. Frage

b) Auszahlungen sind wie folgt geregelt
Sparbuch: bis zur Höhe des Kontostandes
Girokonto: bis zur Höhe des Kreditlimits
Bausparkonto: bis zur Höhe des Kontostandes aber nur, wenn vorher die Vertragssumme erreicht wurde

Zur Klassenhierarchie für euch:
Sparbuch erbt von Mutterklasse "Konto" die Variable "Kontostand"
Girokonto hat eine lokale Variable "Kreditlimit"
Bausparkonto erbt "Kontostand" von "Konto" und hat eine lokale Variable "Vertragssumme"

Wie ich vorgehen würde: Bei Sparbuch in der Methode auszahlen(int auszahlung) eine if-Abfrage, bei Girokonto dasselbe, nur statt "Kontostand" eben "Kreditlimit".
Java:
if(auszahlung > Kontostand){
Kontostand = Kontostand - auszahlung;
}
// Methode fürs Einzahlen
public void einzahlen(int einzahlung){
Kontostand = Kontostand + einzahlung;
}

Wie gehe ich nun vor beim Bausparkonto? Habe da überhaupt keine Idee wie ich das mit der Vertragssumme mache.


3. Frage

c) Implementieren Sie zusätzlich eine Methode zur Berechnung der Zinsen
beim Sparbuch und Bausparkonto wird der Zins auf Basis des Kontostandes berechnet
beim Girokonto gibt es nur Sollzinsen, für die ein Überziehungszinssatz zugrunde gelegt wird


Beim Sparbuch und Bausparkonto gibts ein Problem. Die Klasse Konto weiß ja nicht, dass es die Unterklassen gibt, wodurch getZinssatz() nicht funktioniert, und die Variable Zinssatz in der Klasse Konto implementieren bringt nichts, da sie für zwei Klassen gelten soll, die unterschiedliche Zinssatz-Werte bekommen sollen.

Die Klasse Girokonto hat eine lokale Variable "Ueberziehungszins", womit sich für mich folgender Code ergibt:

Java:
    public void berechneZins(){
        double Zinsen;
        Zinsen = (Kontostand/100)*Ueberziehungszins;
        Kontostand = Kontostand + Zinsen;
       
    }

Hoffe auf hilfreiche Tipps! Gruß!
 
Zuletzt bearbeitet:

Madlip

Bekanntes Mitglied
So wie ich das heraus lese ist "Konto" eine Klasse, richtig? Wenigstens eine abstracte Klasse?. Dort kannst du wie in erstens beschrieben deine Variablen Zins und Überziehungszins hinein packen.

Die Ausprägungen (Sparbuch, Girokonto, Bausparkonto) erben dann von dieser.
Konto hat einige Methoden implementiert (bestenfalls diese die alle gemeinsam haben). Somit müssen beispielsweise alle "Kind-Klassen" die Methode auszahlen implementieren, in diesen Kind-Klassen kannst du dann die Logik der Kind-Klasse entsprechend implementieren -> keine If-Abfrage "wer ich bin" nötig. Das gleiche gilt dann für 3. auch.

Nur ich frage mich gerade ob es nicht besser wäre aus der Klasse Konto ein Interface zu machen, weil an sich hält ja Konto keine Logik, sondern ist viel mehr ein "Vertrag", sprich die, die Konto implementieren müssen gewisse Voraussetzungen erfüllen.
 

Schwupsi

Aktives Mitglied
So wie ich das heraus lese ist "Konto" eine Klasse, richtig? Wenigstens eine abstracte Klasse?. Dort kannst du wie in erstens beschrieben deine Variablen Zins und Überziehungszins hinein packen.

Die Ausprägungen (Sparbuch, Girokonto, Bausparkonto) erben dann von dieser.
Konto hat einige Methoden implementiert (bestenfalls diese die alle gemeinsam haben). Somit müssen beispielsweise alle "Kind-Klassen" die Methode auszahlen implementieren, in diesen Kind-Klassen kannst du dann die Logik der Kind-Klasse entsprechend implementieren -> keine If-Abfrage "wer ich bin" nötig. Das gleiche gilt dann für 3. auch.

Nur ich frage mich gerade ob es nicht besser wäre aus der Klasse Konto ein Interface zu machen, weil an sich hält ja Konto keine Logik, sondern ist viel mehr ein "Vertrag", sprich die, die Konto implementieren müssen gewisse Voraussetzungen erfüllen.

"Konto" ist eine abstrakte Klasse, richtig. Von ihr erben "Sparbuch", "Girokonto" und "Bausparkonto" folgendes:
String name;
String Anschrift;
int Kontostand;
_____________
einzahlen(int einzahlung) // Beim Bausparkonto muss die Einzahlmethode etwas spezialisiert werden.

Dass "Konto" abstrakt ist, ist in der Aufgabenstellung so vorgegeben.
Desweiteren sind die Klassen wie folgt zu erstellen:

"Sparbuch"
double Zinssatz;
________________
auszahlen()

"Girokonto"
int Kreditlimit;
double Ueberziehungszins;
____________________
auszahlen()

"Bausparkonto"
double Zinssatz;
int Vertragssumme;
______________
einzahlen()
auszahlen()

Mein Hauptproblem ist, dass ich in der berechneZins() - Methode in der Kontoklasse nicht auf die Variable Zinssatz zugreifen kann. Weder mit getZinssatz() noch mit Klasse.Zinssatz.
Sollte ich hier zusätzlich ein Interface erstellen, das Zinssatz zur Verfügung stellt? Aber hier gibts dann wieder das Problem, dass der Zinssatz final ist und bei "Sparbuch" sowie "Bausparkonto" unterschiedliche Werte vorliegen.
 

Joose

Top Contributor
Mein Hauptproblem ist, dass ich in der berechneZins() - Methode in der Kontoklasse nicht auf die Variable Zinssatz zugreifen kann. Weder mit getZinssatz() noch mit Klasse.Zinssatz.
Sollte ich hier zusätzlich ein Interface erstellen, das Zinssatz zur Verfügung stellt? Aber hier gibts dann wieder das Problem, dass der Zinssatz final ist und bei "Sparbuch" sowie "Bausparkonto" unterschiedliche Werte vorliegen.

Ist auch nicht notwendig von der Methode "berechneZins" in der Klasse "Konto" auf die Variable Zinssatz zuzugreifen.
Diese Methode berechnet einfach den normalen Zinsatz eines Konto. In der Klasse Bausparkonto überschreibst du dann die Methode "berechneZins" und kannst dort auch auf die Variable "Zinssatz" zugreifen.
Mittels "super.berechneZins()" kannst du auch die Methode der Superklasse aufrufen und deren Ergebnis zur weiteren Verarbeitung/Berechnung verwenden. Das hat den Vorteil das der normale Zins nur an einer Stelle berechnet wird -> Kontoklasse, und in den spezifischen Klassen wird er nur noch modifiziert - natürlich nur ein Beispiel, weiß jetzt nicht genau was alles wie berechent werden soll ;)
 

Schwupsi

Aktives Mitglied
Ist auch nicht notwendig von der Methode "berechneZins" in der Klasse "Konto" auf die Variable Zinssatz zuzugreifen.
Diese Methode berechnet einfach den normalen Zinsatz eines Konto. In der Klasse Bausparkonto überschreibst du dann die Methode "berechneZins" und kannst dort auch auf die Variable "Zinssatz" zugreifen.

Verstehe nicht wie ich in der Klasse "Konto" die Zinsen ohne "Zinssatz" berechnen soll?
Kannst du mir da einen Codeschnipsel liefern, wie du dir die Methode vorstellst?
 

Schwupsi

Aktives Mitglied
Dann sind die Zinsen eben bei 0%?

Ich bin mir nicht ganz sicher, ob ich mein Problem verständlich dargestellt habe.
Ich habe in einer Testklasse den Befehl "konto.berechneZins();".
"konto" ist ein übergebener Parameter an die Methode "Test()" der jeweils Objekte von allen Klassen enthält und nacheinander die Zinsen von allen berechnet. Wenn ich mit der Maus über "konto.berechneZins()" fahre, dann steht da, dass die Methode berechneZins() in der Klasse "Konto" aufgerufen wird, die jedoch keine Zinsen liefern kann, deshalb funktioniert das Programm auch nicht.

Ich weiß nicht wie ich das lösen soll.
 

Joose

Top Contributor
Ich habe in einer Testklasse den Befehl "konto.berechneZins();".
"konto" ist ein übergebener Parameter an die Methode "Test()" der jeweils Objekte von allen Klassen enthält und nacheinander die Zinsen von allen berechnet.

Von welchem Typ ist dieser Parameter "konto"? Von der Basisklasse "Konto" nehme ich an? => Du musst in der Klasse "Konto" nur eine Methode "berechneZins" anbieten. Diese kann aber ebenfalls als abstrakt definiert werden. Dadurch zwingst du die Kindklassen diese Methode zu implementieren. Was die jeweilige Kindklasse dann berechnet bleibt ihr überlassen.
Die Klasse "Konto" muss dadurch nicht selbst die Berechnung durchführen
 

Schwupsi

Aktives Mitglied
Von welchem Typ ist dieser Parameter "konto"? Von der Basisklasse "Konto" nehme ich an? => Du musst in der Klasse "Konto" nur eine Methode "berechneZins" anbieten. Diese kann aber ebenfalls als abstrakt definiert werden. Dadurch zwingst du die Kindklassen diese Methode zu implementieren. Was die jeweilige Kindklasse dann berechnet bleibt ihr überlassen.
Die Klasse "Konto" muss dadurch nicht selbst die Berechnung durchführen

Genau, konto ist vom Typ "Konto". Werde es gleich mal versuchen die Methode als abstract zu definieren.

EDIT: Habe die Methode als abstract definiert, aber es kommt trotzdem nicht das richtige raus. Die Ausgabe gibt einmal das Konto ohne Zinsberechnung und danach durchläuft es die berechneZins() Methode und gibt das Konto mit Zinsen nochmal aus, aber bei beiden ist der Betrag gleich :(

Als Beispiel die Methode aus der Klasse "Sparbuch":

Java:
public void berechneZins(){
int Zinsen;
Zinsen = (int) ((Kontostand/100)*Zinssatz);
Kontostand = Kontostand + Zinsen;
}

Müsste eigentlich gehen oder?
 
Zuletzt bearbeitet:

Schwupsi

Aktives Mitglied
Ok, nun funktioniert das Programm. Das Problem lag darin, dass ich in der Klasse "Konto" die einzahlen(), auszahlen() und berechneZins() Methoden nicht als abstrakt definiert habe.

Nun gibt es bei der Berechnung des Bausparkontos ein kleines Problem. Dort ist die Auszahlmethode etwas speziell, die Vorgabe lautet:

b) Auszahlungen sind wie folgt geregelt:
Bausparkonto: bis zur Höhe des Kontostandes aber nur, wenn vorher die Vertragssumme erreicht
wurde

Vertragssumme ist 1000!

Habe somit die Methode wie folgt implementiert:
Java:
public void auszahlen(double auszahlung){
boolean summeerreicht;
summeerreicht = false;
if((Kontostand >= Vertragssumme) && (auszahlung <= Kontostand) && (summeerreicht == false)){
Kontostand = Kontostand - auszahlung;
summeerreicht = true;
}
else if ((auszahlung <= Kontostand) && (summeerreicht == true)){
Kontostand = Kontostand - auszahlung;
}
}

Die Buchungen sind:
+500 (Kontostand: 500)
-400 (geht nicht, da Vertragssumme noch nicht erreicht)
+600 (Kontostand 1100 - Vertragssumme erreicht!)
-800 (Kontostand: 300 / geht jetzt, da Vertragssumme erreicht wurde)

-100 diese 100 bucht er mir nicht ab! weiß nicht warum :/
Kontostand müsste nun 200 sein und darauf dann die Zinsen. Aber er gibt mir 300 aus und berechnet auf die 300 die Zinsen.
 

Tarrew

Top Contributor
Am Anfang deiner Methode setzt du 'summeerreicht' immer auf false. Wenn es einmal true war brauchst du es aber nicht mehr auf false setzen. Deswegen trifft beim Kontostand von 300 keine der beiden Abfragen zu.

'summeerreicht' könnte also zB ein Attribut der Klasse sein.
 

Schwupsi

Aktives Mitglied
Am Anfang deiner Methode setzt du 'summeerreicht' immer auf false. Wenn es einmal true war brauchst du es aber nicht mehr auf false setzen. Deswegen trifft beim Kontostand von 300 keine der beiden Abfragen zu.

'summeerreicht' könnte also zB ein Attribut der Klasse sein.

Perfekt! "summeerreicht" als Klassenattribut funktioniert! :) Danke!!

Kann geclosed werden.
 

Neue Themen


Oben