![]() |
Daten in einer Klassenhierachie ablegen
Hallo,
ich weiß nicht genau wie ich in Object Pascal an folgendes Problem herangehe. Ich möchte gerne die Struktur eines Autos zum Beispiel in einer Klassenhierachie ablegen. Beispiel: Auto besteht aus Karosserie, Reifen, Türen, etc. Die Klasse TAuto soll also eine Liste enthalten, welche dann die anderen Objekte TKarosserie, TReifen, TTÜren enthält. Es kann jetzt natürlich vorkommen, dass ein Auto vier oder fünf Türen hat, bzw. die Türen auch wieder aus einer Struktur besteht. Es sollte also ein Objekt in TAuto geben, wo man andere hinterlegen kann: TAuto | |- Objekte : Tweissnichwas Jetzt soll TAuto.Objekte[1] := Karosserie; TAuto.Objekte[2] := Türen;. In Türen soll dann natürlich auch jede einzelene Tür hinterlegt sein. Also müsste TTüren ebenfalls eine Objektliste enthalten, welche dann immer ein Objekt TTür enthält mit den entsprechenden Eigenschaften. TAuto.Objekte[2] as TTüren.Obejekte[1] := Tür bzw. TTüren.Obejekte[2] := Heckklappe. Wie bilde ich so etwas in Delphi ab, wie füge ich neue Objekte ein, wie kann ich auf Eigenschaften zugreifen, etc. Gibt es hierzu vielleicht ein gutes Beispiel oder eine Erklärung ?? Besten Dank Stefan Blankenagel |
Re: Daten in einer Klassenhierachie ablegen
Hallo,
jedes Formular macht das:
Unter Win32 wird es nicht so offensichtlich, aber implizit machen die Verknüpfungen in der Dfm-Datei nichts anderes. Schau Dir dies einmal genauer an und übertrage es auf Dein Problem. Vielleicht kommst Du damit weiter. Gruß Jürgen |
Re: Daten in einer Klassenhierachie ablegen
Also ich hätte erstmal einen Autotyp gemacht:
Delphi-Quellcode:
Dann den Türentyp und Reifentyp:
type
TCar = record doors : array of TDoor; tires : array of TTire; end;
Delphi-Quellcode:
Du könntest auch statt den Records, Klassen nehmen. Die können dann auch Methoden enthalten und müssen erzeugt/zerstört werden.
type
TDoor = record width, height : Extended; ... end; type TTire = record radius : Extended; tireType : Byte; ... end; |
Re: Daten in einer Klassenhierachie ablegen
Hallo,
ja ich hatte es eigentlich mit Klassen vor, da ich dann wirklich dort Methoden einbauen kann. Werde mich noch einmal in diese Richtung damit beschäftigen. Mit freundlichen Grüßen Stefan Blankenagel |
Re: Daten in einer Klassenhierachie ablegen
Zitat:
So würde es schon anders aussehen :
Delphi-Quellcode:
Der Pkw hat dadurch schon direkt eingebaute Türen, Fenster usw. Das TCar hat die noch nicht. Beispiele in dieser Richtung finden sich auch zu Dutzenden im Internet. Man muß sie eben mal lesen und umsetzen. :zwinker:
type
TCar = class Breite, Höhe, Länge : real; AnzahlTueren, AnzahlFenster : integer; end; TPkw = class (TCar) Schiebedach : boolean; end; Edit : Delphi-Tag falsch gesetzt und gleich der nächste Tip : Methoden lassen sich da auch gut einbauen. Trotzdem würde ich zunächst mal die Datenstrukturen richtig aufbauen. |
Re: Daten in einer Klassenhierachie ablegen
Für die Programmentwicklung ist eine genaue Planung der Datenstruktur sehr wichtig. Deshalb mac h ich mir ja die Gedanken.
Ich habe mir jetzt folgende Datenstruktur gebastelt:
Delphi-Quellcode:
Die Prozedur zum einfügen von Daten sind diese:
TLeuchte = class
private FZielort : string; FAdresse : integer; public constructor create; destructor Destroy; override; property Zielort : string read FZielort write FZielort; property Adresse : integer read FAdresse write FAdresse; end; TStromkreis = class private FAdresse : integer; FLeuchten : Array of TLeuchte; function GetLeuchte(index:integer):TLeuchte; public constructor create; destructor destroy; override; property Leuchte[index:integer]:TLeuchte read GetLeuchte; default; property Adresse : integer read FAdresse write FAdresse; function get_Anzahl_Leuchten : integer; procedure Add_Leuchte(vAdresse : integer; vZielort: string); procedure clear_Leuchten; end; TEinschub = class private FStromkreise : Array of TStromkreis; FAdresse : integer; FTyp : integer; function GetStromkreis(index:integer):TStromkreis; public constructor create; destructor destroy; override; property typ : integer read FTyp write FTyp; property Stromkreis[index:integer]:TStromkreis read GetStromkreis; default; property Adresse : integer read FAdresse write FAdresse; function get_Anzahl_Stromkreise : integer; procedure Add_Stromkreis(vAdresse:integer); end; TGeraet = class private FZielort : string; FAdresse : integer; FTyp : integer; FEinschuebe : Array of TEinschub; function getEinschub(index:integer):TEinschub; public constructor create; destructor destroy; override; property Einschub[index:integer]: TEinschub read getEinschub; default; property Zielort : string read FZielort write FZielort; property Typ : integer read FTyp write FTyp; property Adresse : integer read FAdresse write FAdresse; function get_Anzahl_Einschuebe : integer; procedure Add_Einschub(vTyp : integer; vAdresse: integer); end;
Delphi-Quellcode:
Wenn nun die Struktur mit Daten gefüllt werden sollen, kommt eine Zugriffsverletzung:
procedure TGeraet.Add_Einschub(vTyp : integer; vAdresse : integer);
var idx : integer; vEinschub : TEinschub; begin idx := get_Anzahl_Einschuebe; SetLength(FEinschuebe, idx + 1); vEinschub := TEinschub.create; FEinschuebe[idx] := vEinschub; vEinschub.Free; FEinschuebe[idx].Typ := vTyp; FEinschuebe[idx].Adresse := vAdresse; end; procedure TEinschub.Add_Stromkreis(vAdresse : integer); var idx : integer; vStromkreis : TStromkreis; begin idx := get_Anzahl_Stromkreise; SetLength(FStromkreise, idx + 1); vStromkreis := TStromkreis.create; FStromkreise[idx] := vStromkreis; FStromkreise[idx].Adresse := vAdresse; vStromkreis.Free; end; procedure TStromkreis.Add_Leuchte(vAdresse : integer; vZielort: string); var idx : integer; vLeuchte : TLeuchte; begin idx := get_Anzahl_Leuchten; SetLength(FLeuchten, idx + 1); vLeuchte := TLeuchte.create; FLeuchten[idx] := vLeuchte; vLeuchte.Free; FLeuchten[idx].Adresse := vAdresse; FLeuchten[idx].Zielort := vZielort; end;
Delphi-Quellcode:
Ich dachte erst, es liegt daran, dass ich schon zwei Stromkreise eingefügt habe und jetzt eine Leuchte in Stromkreis 1 einfüge, wodurch aber Speicherplatz im Bereich zwischen Stromkreis 1 und Stromkreis 2 reserviert werden muss. Auch nach Auskommentierung von Add_Stromkreis(2) erscheint in der folgenden Zeile die Zugriffsverletzung.
FGeraet := TGeraet.Create;
FGeraet.Add_Einschub(JSUSV23, 1); FGeraet.Einschub[0].Add_Stromkreis(1); FGeraet.Einschub[0].Add_Stromkreis(2); FGeraet.Einschub[0].Stromkreis[0].Add_Leuchte(1, 'Toilette Herren'); //Hier kommt eine Zugriffsverletzung FGeraet.Einschub[0].Stromkreis[0].Add_Leuchte(2, 'Toilette Damen'); FGeraet.Einschub[0].Stromkreis[0].Add_Leuchte(3, 'Eingang'); FGeraet.Einschub[0].Stromkreis[0].Add_Leuchte(4, 'Ausgang'); FGeraet.Einschub[0].Stromkreis[0].Add_Leuchte(5, 'Irgendein Text'); FGeraet.Einschub[0].Stromkreis[1].Add_Leuchte(6, 'Eine 6. Leuchte'); FGeraet.Einschub[0].Stromkreis[1].Add_Leuchte(5, 'Toilette Herren'); FGeraet.Einschub[0].Stromkreis[1].Add_Leuchte(4, 'Toilette Damen'); FGeraet.Einschub[0].Stromkreis[1].Add_Leuchte(3, 'Eingang'); FGeraet.Einschub[0].Stromkreis[1].Add_Leuchte(2, 'Ausgang'); FGeraet.Einschub[0].Stromkreis[1].Add_Leuchte(1, 'Irgendein Text'); Gruß Stefan Blankenagel |
Re: Daten in einer Klassenhierachie ablegen
Zitat:
Delphi-Quellcode:
Zu deinem Problem: Debug mal in "Add_Leuchte" und sag uns, wo dort der Fehler auftritt... Vielleicht ist "get_Anzahl_Leuchten" "defekt" :D
{ * Variante 1 = Direkte Instanzierung + with * }
procedure TGeraet.Add_Einschub(vTyp : integer; vAdresse : integer); var idx : integer; begin idx := get_Anzahl_Einschuebe; SetLength(FEinschuebe, idx + 1); with FEinschuebe[idx] := TEinschub.create do begin Typ := vTyp; Adresse := vAdresse; end; end; { * Variante 2 = direkte Instanzierung * } procedure TEinschub.Add_Stromkreis(vAdresse : integer); var idx : integer; begin idx := get_Anzahl_Stromkreise; SetLength(FStromkreise, idx + 1); FStromkreise[idx] := TStromkreis.create; FStromkreise[idx].Adresse := vAdresse; end; { * Variante 3 = direkte Instanzierung + Verzicht, auf eigene Methoden * } procedure TStromkreis.Add_Leuchte(vAdresse : integer; vZielort: string); begin SetLength(FLeuchten, Length(FLeuchten) + 1); FLeuchten[High(FLeuchten)] := TLeuchte.create; FLeuchten[High(FLeuchten)].Adresse := vAdresse; FLeuchten[High(FLeuchten)].Zielort := vZielort; // Ich bin mir nicht sicher, ob es hier mit with effektiver ist, da nur einmal die "High()" - Methode aufgerufen werden muss (siehe Variante 1) end; |
Re: Daten in einer Klassenhierachie ablegen
Ist der Titel des Themas eventuell gar nicht mehr gültig ? Ich sehe jedenfalls nur eine Aneinanderreihung verschiedener Typen, die nichts miteinander zu tun haben. Da ist nichts zu sehen in Richtung "Klassenhierarchie". :shock: Deshalb ist das verwendete override in den Deklarationen auch überflüssig. Glaube zwar nicht, daß das einen bemerkbaren Fehler verursacht, aber es ist trotzdem einer. Dann noch als Beispiel das FAdresse. Wieso wird das überall neu deklariert ? Warum nicht tatsächlich eine Hierarchie, die damit beginnt alles gemeinsame erst mal in eine Basisklasse zu packen und die dann zu vererben. Dabei wird bei den Nachfolgern nur noch das neu deklariert, was auch tatsächlich hinzu kommt. Das gilt nicht nur für Daten, sondern auch für eventuell notwendige neue Methoden.
Ich gehe jetzt mal von dem Auto weg. Geometrische Figuren eignen sich besser. Fangen wir beim Punkt an. Was braucht der ? Eigentlich nur Koordinaten. Na gut er kriegt noch eine Farbe :
Delphi-Quellcode:
Dann kommt der Kreis. Der hat auch einen Mittelpunkt und eine Farbe. Es kommt hinzu : ein Radius und ich muß ihn zeichnen, also eine durch dem Mittelpunkt und den Radius bestimmte Fläche ausfüllen. Der Punkt hat aber bereits einiges, was man für den Kreis braucht und der sieht deshalb so aus :
TPunkt = class
x,y : integer; Farbe : TColor; end;
Delphi-Quellcode:
Mehr braucht man nicht, das was in der Deklaration nicht zu sehen ist, das liefert schon der Punkt. Jetzt gehen mir langsam die Ideen aus. Ellipse ist mir zu schwer. :mrgreen: Aber wie wäre es noch mit einem berechneten Kreis ? Der soll genauso angezeigt werden, hat auch einen Mittelpunkt und einen Radius. Zusätzlich will ich aber die Fläche und den Umfang wissen:
TKreis = class (TPunkt)
Radius : integer; protected procedure Zeichnen; virtual; end;
Delphi-Quellcode:
Der Rest steckt bereits im Kreis (procedure Zeichnen) oder sogar schon im Punkt (x,y,Farbe). Es kommt eben noch was hinzu. Dann noch ein Quadrat und es stellt sich die Frage, wo man da ansetzen soll. Es hat keinen Radius, sondern sagen wir eine Kantenlaenge. Anders gezeichnet werden muß es auch. Wegen des erwähnten "override" benutze ich aber den Kreis und ignoriere den Radius :
TBerechneterKreis = class (TKreis)
Flaeche, Umfang : real; protected procedure BerechneFlaeche; virtual; procedure BerechneUmfang; virtual; end;
Delphi-Quellcode:
Da ich vom Kreis her komme, brauche ich ja eine komplett andere Zeichenmethode. Deshalb wird die hier neu deklariert und per override wird die alte vollkommen ignoriert. Bräuchte ich tatsächlich solche Figuren, würde ich wohl nach dem TPunkt eine Weggabelung in der Hierarchie machen. Kreise, Ellipsen usw. und das andere wäre Quadrat, Rechteck, wie heißt noch das schiefe Quadrat ? :gruebel: Da kämen dann auch Winkel ins Spiel usw. So, hoffe mal, daß das hier nicht nur was für Sakura ist. :mrgreen:
TQuadrat = class (TKreis)
KantenLaenge : integer; protected procedure Zeichnen; override; end; |
Re: Daten in einer Klassenhierachie ablegen
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
vielleicht kann mir noch einmal jemand helfen. Beiliegender Programmcode erzeugt in folgender Prozedur eine Zugriffsverletzung:
Delphi-Quellcode:
Und ich habe leider keine Ahnung, warum dies so ist. Anscheinend existiert etwas nicht mehr die Länge von der Funktion get_Anzahl_Leuchten ist auf einmal ziemlich groß.
procedure TStromkreis.Add_Leuchte(vAdresse : integer; vZielort: string);
var idx : integer; vLeuchte : TLeuchte; begin idx := get_Anzahl_Leuchten + 1; SetLength(FLeuchten, idx + 1); vLeuchte := TLeuchte.create; FLeuchten[idx] := vLeuchte; FLeuchten[idx].Adresse := vAdresse; FLeuchten[idx].Zielort := vZielort; end; mfg Stefan |
Re: Daten in einer Klassenhierachie ablegen
Delphi-Quellcode:
FLeuchten[idx-1] := vLeuchte;
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:51 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz