Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   wie verschiedene Objekttypen sinnvoll speichern? (https://www.delphipraxis.net/171323-wie-verschiedene-objekttypen-sinnvoll-speichern.html)

martin28 31. Okt 2012 13:53

wie verschiedene Objekttypen sinnvoll speichern?
 
Hi alle zusammen.

Ich grüble schon seit einigen Tagen über folgendes Problem:
Bsp.
Klasse C_Fahrzeug.
Abgeleitet sind C_Motorrad, C_Auto und C_LKW.

Der Benutzer kann als Beispiel mit 4 Buttons Objekte der abgeleiteten Klassen erzeugen und löschen. Dabei hat er aber die Auswahl welchen der 3 er erzeugen will.

Meine Frage: Wie kann ich dies sinnvoll speichern? Zur Zeit nutze ich folgende Konstruktion:
Delphi-Quellcode:
var buttonzuordnung : array[0..3] of record
       typ : integer;
       autotyp : c_auto;
       motorradtyp : c_motorrad;
       lkwtyp : c_lkw;
    end;
Somit muss ich jedesmal, wenn der Benutzer einen anderen Typ wählt :
- die Auswahl in typ speichern
- vorher altes objekt schließen
- zum Schluss ein neues Objekt vom neuen Typ erstellen.

Ich meine, bei diesen 3 Klassen ist es noch erträglich. Wenn aber 10 oder 20 abgeleitete Klassen zur Verfügung stehen, wird es schnell unübersichtlich.

Hat einer einen Tipp für mich ?

Grüße,

Martin

Bernhard Geyer 31. Okt 2012 15:06

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Wie wäre es mit XML?

uligerhardt 31. Okt 2012 15:15

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Mit "Speichern" meinst du jetzt nicht "Objekt in eine Datei auf der Festplatte speichern", oder hab ich dich falsch verstanden?

Ich glaube, du suchst
Delphi-Quellcode:
var buttonzuordnung : array[0..3] of C_Fahrzeug;
und statt
Delphi-Quellcode:
typ
sowas wie
Delphi-Quellcode:
if buttonzuordnung[1] is c_auto then ...
. Statt der
Delphi-Quellcode:
is
-Konstruktion wären virtuelle Methoden natürlich wesentlich schöner.

Das mit
Delphi-Quellcode:
array[0..3] of C_Fahrzeug;
funktioniert, weil du Referenzen auf Objekte einer abgeleiteten Klasse einer Basisklassenreferenz zuweisen kannst, also z.B.
Delphi-Quellcode:
var
  fahrzeug: C_Fahrzeug;
begin
  fahrzeug := C_Auto.Create;
end;
Ohne das würde die ganze OO nicht funktionieren.

BTW: Tu dir und uns den Gefallen und benenn deine Klassen Delphi-konform: TFahrzeug, TAuto etc.

martin28 2. Nov 2012 21:25

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Hi.

@uligerhardt

Die Variante mit array[0..3] of TFahrzeug funktioniert ganz gut. Ich kann die einzelnen abgeleiteten Klassen dort ablegen. Damit ergibt sich für mich jetzt ein weiteres Problem:

Nehmen wir an, das TFahrzeug eine Funktion vom Typ
Code:
function tanken():byte; virtual; abstract;
besitzt.

Für TAuto und TMotorrad nutze ich diese Funktion dann folgendermaßen
Code:
function tanken():byte; reintroduce;
Für die Klasse TLkw möchte ich aber
Code:
function tanken(adblue:boolean):byte; reintroduce;
nutzen.

Wenn ich die Objekte einzeln erzeugen würde, könnte ich die Funktion auch problemlos nutzen
Code:
var golf:TAuto;
var laster:TLkw;
begin
   golf := TAuto.create;
   golf.tanken()
   laster := TLkw.create;
   laster.tanken(TRUE);


Da ich aber jetzt die Deklaration über
Code:
var fahrzeugpool : array[0..3] of TFahrzeug;
und
Code:
   fahrzeugpool[0] := TAuto.create;
   fahrzeugpool[1] := TLkw.create;
nutze, bekomme ich bei
Code:
   adblue_tanken := TRUE;
   fahrzeugpool[1].tanken(adblue_tanken);
ein Compilerfehler. (Too many actual parameters)
Ist ja auch klar, da in der TFahrzeug Funktion tanken() kein weiterer Parameter vorhanden ist.

Wie kann ich dennoch auf die tanken-Funktion vom LKW mit dem Parameter zugreifen?

Grüße,

Martin

PS. habe jetzt alle Namen zur leichteren Lesbarkeit angepasst :-)

uligerhardt 2. Nov 2012 21:42

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Zitat:

Zitat von martin28 (Beitrag 1189545)
Für TAuto und TMotorrad nutze ich diese Funktion dann folgendermaßen
Code:
function tanken():byte; reintroduce;

Vermutlich willst du
Delphi-Quellcode:
override
statt
Delphi-Quellcode:
reintroduce
. Sonst muss die Methode in der Basisklasse ja nicht als virtuell deklariert sein.

Zitat:

Zitat von martin28 (Beitrag 1189545)
Für die Klasse TLkw möchte ich aber
Code:
function tanken(adblue:boolean):byte; reintroduce;
nutzen.

Wenn ich die Objekte einzeln erzeugen würde, könnte ich die Funktion auch problemlos nutzen
Code:
var golf:TAuto;
var laster:TLkw;
begin
   golf := TAuto.create;
   golf.tanken()
   laster := TLkw.create;
   laster.tanken(TRUE);


Da ich aber jetzt die Deklaration über
Code:
var fahrzeugpool : array[0..3] of TFahrzeug;
und
Code:
   fahrzeugpool[0] := TAuto.create;
   fahrzeugpool[1] := TLkw.create;
nutze, bekomme ich bei
Code:
   adblue_tanken := TRUE;
   fahrzeugpool[1].tanken(adblue_tanken);
ein Compilerfehler. (Too many actual parameters)
Ist ja auch klar, da in der TFahrzeug Funktion tanken() kein weiterer Parameter vorhanden ist.

Wie kann ich dennoch auf die tanken-Funktion vom LKW mit dem Parameter zugreifen?

Entweder casten:
Delphi-Quellcode:
TLkw(fahrzeugpool[1]).tanken(adblue_tanken);
Oder du nutzt eine Zwischen-Variable:
Delphi-Quellcode:
var
  laster: TLkw;
begin
 laster := TLkw.Create;
 fahrzeugpool[1] := laster;
 laster.tanken(True);
Zitat:

Zitat von martin28 (Beitrag 1189545)
PS. habe jetzt alle Namen zur leichteren Lesbarkeit angepasst :-)

Du wirst mir noch dankbar sein. :mrgreen::lol:

Bummi 2. Nov 2012 21:45

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Delphi-Quellcode:
TLKW(fahrzeugpool[1]).tanken(adblue_tanken);
Einfacher wäre es wenn Du tanken zwar virtual aber nicht abstract deklarierst.

Delphi-Quellcode:
 TFahrzeug=Class
    function tanken():byte; virtual;
  End;
  TLKW=Class(TFahrzeug)
    function tanken():byte; override;
  end;

//__________


{ TFahrzeug }

function TFahrzeug.tanken: byte;
begin
  Showmessage('Fahrzeug tanken')
end;

{ TLKW }

function TLKW.tanken: byte;
begin
   Showmessage('LKW tanken;')
end;

procedure TForm3.Button1Click(Sender: TObject);
var
 f:TFahrzeug; //<<*
begin
   f:=TLKW.Create; //<<*
   f.tanken;      // "LKW tanken"
end;

QuickAndDirty 3. Nov 2012 10:50

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Wäre für ihn nicht ein Record mit case am besten?

die andere Möglichkeit wäre.
"Tanken" in beiden Versionen überladen in die Basisklasse aufzunehmen.

Sir Rufo 3. Nov 2012 11:03

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Eine andere Möglichkeit wäre eine von der Basisklasse eine weitere Basisklasse zu erstellen mit der geänderten Methode und die konkreten davon ableiten.

Für die Verarbeitung der einzelnen Instanzen würde sich dann das Visitor-Pattern empfehlen, wo auf diese Abweichungen reagiert werden kann.

sx2008 3. Nov 2012 11:39

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Diese "tanken"-Methode ist schon in der Basisklasse kaputt.
Beim Tanken gibt es zwei wichtige Parameter: die Menge und die Art des Sprits.
Delphi-Quellcode:
TSpritSorte = (sDefault{=Spritsorte die ein Fahrzeug normalerweise benötigt},
   sBenzin, sDieselPkw, sSuperE5, sSuperE10);
TFahrzeug=Class
  procedure tanken(liter:Currency; sorte:TSpritSorte); virtual;
End;
Wenn man Klassen ableitet, dann darf man nicht die Signatur von virtuellen Methoden in abgeleiteten Klassen ändern.
Man muss virtuelle Methoden so anlegen, dass sie immer passen.

Falls es trotzdem klemmt liegt das daran, das ein Fahrzeug nicht zwingend betankt werden muss.
Ein Fahrrad ist z.B. auch ein Fahrzeug; braucht aber keinen Sprit.
Beim LKW ist das Nachfüllen von Harnstoff (AdBlue) eher ein Wartungsvorgang als ein Tankvorgang (so wie man Motoröl und Wischwasser nachfüllt).

siehe auch: Kreis-Ellipse-Problem

Sir Rufo 3. Nov 2012 15:08

AW: wie verschiedene Objekttypen sinnvoll speichern?
 
Das sehe ich nicht so, ich würde die Methode tanken eher so aufbauen, dass ich übergebe, wo das Fahrzeug tanken soll.

Welchen Treibstoff und welche Menge, dass weiß das Fahrzeug selber (volltanken oder nur soviel um das nächste Ziel zu erreichen) und kann dann die "Tankstelle" fragen, ob es den Treibstoff xy dort in ausreichender Menge noch gibt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:59 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz