Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Problem bei Vererbung von Klassen


Desert Storm - Di 20.02.07 15:24
Titel: Problem bei Vererbung von Klassen
Ich habe eine Klasse die heißt "tKonto" von dieser Klasse hab ich wieder 2 Klassen abgeleitet.
Eine Klasse heißt "tGeldkonto" die sich praktisch wie ein normales Girokonto verhält.
Die zweite Klasse heißt "tDarlehenskonto" auf die man nur Geld einzahlen, aber nicht abheben kann.

Jetzt ist mein Problem wie ich eine Art Sperre in die eine Klasse einbaun kann, damit man nur Geld einzahlen kann.
Dabei wird Geld üder die Funktion "Einzahlen" eingezahlt. Dabei wird die Kontonummer, und der Betrag übergeben.
Genauso verhält es sich auch bei der Funktion "Auszahlen".

Also wenn jemand eine gute Art für eine Sperre weiß, denn immer her damit:)

MFG


Marco D. - Di 20.02.07 15:42

user profile iconDesert Storm hat folgendes geschrieben:

Jetzt ist mein Problem wie ich eine Art Sperre in die eine Klasse einbaun kann, damit man nur Geld einzahlen kann.
Dabei wird Geld üder die Funktion "Einzahlen" eingezahlt. Dabei wird die Kontonummer, und der Betrag übergeben.
Genauso verhält es sich auch bei der Funktion "Auszahlen".

Du hast doch schon den Ansatz. ;) Sorge einfach dafür, dass der Betrag stets größer Null ist ;)


IngoD7 - Di 20.02.07 15:46
Titel: Re: Problem bei der Umsetzung
user profile iconDesert Storm hat folgendes geschrieben:

Also wenn jemand eine gute Art für eine Sperre weiß, denn immer her damit:)

Abgesehen davon, dass ich höchstwahrscheinlich nicht verstehe, was du meinst, hier der Pulitzer-Preis-verdächtige Vorschlag: Lass die Funktion Auszahlen bei TDarlehenskonto weg. :eyecrazy:

Sollte die Funktion bereits in der Basisklasse TKonto eingebaut sein, so mache sie dort private, lass sie in TDarlehenskonto so (also nichts damit tun) und erhöhe ihre Sichtbarkeit lediglich in TGeldkonto auf public.


Desert Storm - Di 20.02.07 15:51

Ja aber wenn der Betrag stets größer als 0 ist, dann kann ich doch trotzdem etwas abheben oder? Ich versteh nicht ganz was du meinst.

Außerdem sind die Funktionen Ein- und Auszahlen leider nicht Bestandteil der Klasse Konto, sondern einer anderen Klasse.


IngoD7 - Di 20.02.07 22:48

user profile iconDesert Storm hat folgendes geschrieben:
Ich versteh nicht ganz was du meinst.

Wie ich bereits vermutete beruht das dann auf Gegenseitigkeit. ;-)

Aber im Ernst - ggf. musst du nochmal genauer beschreiben, was du vorhast. Evtl. mit Code und so.


Desert Storm - Mi 21.02.07 14:28

Also ich habe eine Klasse die "tKonto" heißt. In dieser Klasse sind nur Attribute. So wie PIN, Kontonummer, usw.
So von dieser Klasse habe ich nun die Klasse "tGeldkonto" abgeleitet, die alle Attribute der Oberklasse enthält. Auf dieses Konto hat der Benutzer vollen Zugriff.
Sprich er kann Geld einzahlen und auch abheben.

Dann hab ich von der Oberklasse noch eine weitere Klasse namens "tDarlehenskonto" abgeleitet. Bei dieser Art von Konto kann man nur Geld einzahlen, aber nicht abheben.

Dann gibt es in einer anderen Klasse, die einen Bankautomaten simuliert die Funktionen "Einzahlen" und "Auszahlen".
Bei beiden sind die Parameter gleich.
Bei "Einzahlen" wird einfach das Geld addiert zum Kontostand und bei "Auszahlen" einfach subtrahiert.
Dabei wird aber bei beiden Funktionen der Parameter "Betrag: integer" als positive Zahl übergeben und erst in der Funktion "Auszahlen" wird dieser Betrag denn vom Kontostand subtrahiert.
Also die Parameterübergabe ist bei beiden gleich. Sie werden nur verschieden verarbeitet.

Und mein Problem ist jetzt, das ich irgendwie verhindern muss, das der Benutzer Geld vom Darlehenskonto abheben kann. Leider weiß ich nicht wie ich das bewerkställigen soll.

Der Syntac für die beiden Funktionen sieht denn z.B. so aus:
Geldautomat.Einzahlen(500, 12345678);
Geldautomat.Auszahlen(500, 12345678);

Dabei ist der erste Parameter der Betrag und der letzte die Kontonummer auf welches Konto der Betrag gebucht oder abgebucht werden soll.
Den restlichen Code kann man sich denn ja denken. Das Geld wir denn einfach zum aktuellen Kontostand addiert oder davon subtrahiert. Das is denn ein Einzeiler. :)

Hoffe das wurde jetzt etwas klarer.
MFG


IngoD7 - Mi 21.02.07 16:43

user profile iconDesert Storm hat folgendes geschrieben:
Hoffe das wurde jetzt etwas klarer.

Ja, gar nicht schlecht erklärt. Zusammen mit deinen anderen beiden Postings hier ergibt das halbwegs Sinn.

Obwohl etwas Code mit deinen Klassendeklarationen wird wohl immer noch notwendig sein.

Ich habe zudem (oder gerade deshalb, weil ich es nicht erkennen kann ohne Code) noch eine Frage:
Dein Geldautomat hat also die beiden Funktionen Einzahlen und Auszahlen. Gut. Nun wird eine davon benutzt. Unabhängig davon welche, muss doch anhand der übergebenen Kontonummer ermittelt werden, welches Konto betroffen ist. Wie machen denn deine Funktionen das?

Laufen die in einer Schleife alle Instanzen von TGeldKonto und TDarlehenskonto durch und gucken, bei welchem Konto die Eigenschaft Kontonummer die passende ist?


Marco D. - Mi 21.02.07 16:56

user profile iconDesert Storm hat folgendes geschrieben:
Ja aber wenn der Betrag stets größer als 0 ist, dann kann ich doch trotzdem etwas abheben oder? Ich versteh nicht ganz was du meinst.

Außerdem sind die Funktionen Ein- und Auszahlen leider nicht Bestandteil der Klasse Konto, sondern einer anderen Klasse.

Ich habe dich so verstanden:
Du willst bei der Funktion Einzahlen verhindern, dass man Geld abheben kann. Dies würde ja einem negativen Geldbetrag entsprechen:

Alter Bestand + (-500) wird zu Alter Bestand - 500

Wenn du also eine if-Abfrage benutzt, die prüft, ob der Betrag immer größer Null ist, dann kannst du eine Geldabhebung über die Funktion Einzahlen verhindern.


Tilo - Mi 21.02.07 17:11

Wenn Du die AuszahlenFunktion sperren willst überschreibe sie in TDarlehenKonto das die Auszahlenfunktion einen "Fehler" liefert.

z.b.


Delphi-Quelltext
1:
raise EZugriff.Create('Du darfst nicht abheben');                    

vorher noch


Delphi-Quelltext
1:
2:
type
    Ezugriff = class(Exception);


Desert Storm - Mi 21.02.07 17:14

An IngoD7:
Also der Benutzer drückt auf einen Button und damit wird das einschieben der EC Karte simuliert. Dabei wird eine Instanz von entweder Geldkonto oder Darlehenskonto erzeugt. Ich hab das denn so gemacht, das egal welches Konto erstellt wird, es immer "Kundenkonto" heißt, damit die Kontonummer in der Routine nich geändert oder durch irgendwelche Schleifen laufen müssen.
Sonst müsste ich bevor ich die Funktion aufrufe einige If-Anweisungen machen und in der Funktion auch. Somit wird der Betrag übergeben und denn wird das einfach mit dem Kundenkonto verarbeitet.

An Marco D.:
Nein ich möchte verhindern das der Benutzer die Funktion Auszahlen benutzt. Einzahlen muss er ja noch können, damit er das Darlehn abbezahlen kann.
Einzahlen und Auszahlen sind zwei voneinander unabhängige Funktionen.

Hier mal die Klassendeklaration von der OBerklasse tKonto. Ist aber nur der wichtige Auszug.

type
tKonto = class(TObject)

public //Attribute
Kontostand : double;
Zinssatz : double;
Kontonummer : integer;
PIN : integer;

end;


Und Hier vom Automaten.

type
tAutomat = class(TObject)

public //Attribute
GeldInhalt : double;

public //Methoden
function Auszahlen (Betrag: integer) :String;
function Einzahlen (Betrag: integer) :String;
function Zinsberechnung : string;
function Kontoauszug : string;
function Kundenpruefung (PIN: integer) : boolean;

end;

MFG

PS: Sry hab mich unten in den Beiträgen vertan. Die Kontonummer wird nich als Parameter übergeben, sondern steht fest in der Funktion als Kundenkonto.Kontostand!


IngoD7 - Mi 21.02.07 17:21

user profile iconTilo hat folgendes geschrieben:
Wenn Du die AuszahlenFunktion sperren willst überschreibe sie in TDarlehenKonto das die Auszahlenfunktion einen "Fehler" liefert.

Auf dem (falschen) Dampfer war ich doch auch schon. Es gibt die Funktion ja nicht in den Konto-Klassen. Die gibt es nur in der Geldautoma-Klasse.
Die Frage, wie er überhaupt auf die Konto-Klassen zugreift, um aus- oder einzuzahlen ist noch völlig offen.

Ich hatte in meinem Vorposting überhaupt erstmal gefragt, wie er denn das Konto identifiziert. In der Auszahlenfunktion müsste er eine Referenz auf das betroffene Konto mit der passenden Kontonummer bekommen. Wie will er sonst den Betrag im Konto ändern...? Hat er die Referenz, so könnte er z.B. über TObject.Classname schauen, ob es ein TDarlehenskonto-Konto ist und dann die Funktion abbrechen.

Aber das ist alles irgendwie Murks. Es sollte jede Konto-Klasse über eigene Methoden verfügen, die den Zugriff klar regeln.


IngoD7 - Mi 21.02.07 17:33

user profile iconDesert Storm hat folgendes geschrieben:
Also der Benutzer drückt auf einen Button und damit wird das einschieben der EC Karte simuliert. Dabei wird eine Instanz von entweder Geldkonto oder Darlehenskonto erzeugt.
Wovon ist denn abhängig, welche Klasse instantiiert wird? Wird das ausgewürfelt?

Ist aber jetzt auch langsam egal.

Irgendwann muss dein Automat sich also entscheiden, ob er den Auszahlenknopf anzeigt oder nicht.
Dafür gibt es ca. 3 Mio. Möglichkeiten. ;-)

Eine davon ist: Du verpasst der Klasse TKonto ein Feld FTyp, welches im Konstruktor von TGeldkonto auf 'Geld' gesetzt wird und im Konstruktor von TDarlehensklasse auf 'Darlehen'.
Dann Pseudocode:

Delphi-Quelltext
1:
2:
3:
4:
5:
Geldautomat.ZeigeEinzahlenknopf;
if Kundenkonto.Typ = 'Geld' then
begin
   Geldautomat.ZeigeAuszahlenknopf;
end;


Desert Storm - Mi 21.02.07 17:44

Nene wird nich ausgewürfelt. Der Benutzer kann vorher wählen, welches Konto erstellt werden soll.

Das anzeigen der Buttons ist unabhängig vom Konto. Es wird jeder Button angezeigt, egal welches Konto ausgewählt ist.
Aber die Idee mit dem Konstruktor find ich gut.
Werd mich da mal dran versuchen.
Danke.

MFG

PS: Sry für die Probleme die ich verursacht hab indem ich zu wenig Infos gegeben hab ;)


IngoD7 - Mi 21.02.07 17:53

user profile iconDesert Storm hat folgendes geschrieben:
Das anzeigen der Buttons ist unabhängig vom Konto. Es wird jeder Button angezeigt, egal welches Konto ausgewählt ist.

Dann eben - aufbauend auf meinen Vorschlag obenPseudocode:

Delphi-Quelltext
1:
2:
if not (Kundenkonto.Typ = 'Geld'then 
  Auszahlen_Verhindern;

Wie auch immer du das mit Leben erfüllst.

user profile iconDesert Storm hat folgendes geschrieben:
Aber die Idee mit dem Konstruktor find ich gut.
Werd mich da mal dran versuchen.
Danke.

Fein. Freut mich. Bitte schön. :)