![]() |
Eigenen Typ in Klasse
Hi all
Ich möchte in einer eigenen Klasse einen Record-Typ in einem Dynamischen Array speichern, nun sollte aber der Record-Typ auch von aussen sichtbar sein. Der User der Klasse soll eine neue Variable des Record-Typs deklarieren können und diese dann an eine Methode der Klasse übergeben. z.B. so:
Delphi-Quellcode:
Leider habe ich keine Ahnung wie ich das in meiner Klasse implementieren muss.
var Foo: TRecord;
Klasse.Add(foo); grz zer00 |
Re: Eigenen Typ in Klasse
Deine add proc könnte so aussehen:
Delphi-Quellcode:
(aus dem kopf)
procedure tetc.add(foo: Tdeinrecord);
begin setlength(derarray, length(derarray)+1) derarray[length(derarray)]:= foo; end; |
Re: Eigenen Typ in Klasse
So vielleicht:
Delphi-Quellcode:
Quellcode ungetestet. Nur so runtergetippt. Auch die Speicherverwaltung der Records(new, dispose) fehlt noch. Sollte aber so ne Idee von dem geben, wie das aussehen könnte. BTW: Warum willst du eigentlich n Record nehmen? Warum nicht auch ne Klasse. Dann könntest du dir die Speicherverwaltung nämlich schenken(TObjectList, ggf. + Template).
TRecord = record
Data: string; Data2: Integer; end; TTest = class(TObject) private FData: TList; public constructor Create; destructor Detroy; override; property: Data: TList read FData write FData; procedure Add(Data: TRecord); end; constructor TTest.Create; begin inherited Create; FList := TList.Create; end; destructor TTest.Destroy; begin FList.Free; inherited Destroy; end; procedure TTest.Add(Data: TRecord); begin FData.Add(@Data); end; mfg Christian |
Re: Eigenen Typ in Klasse
mal ne Frage, ist es nicht "sicherer", alle Daten eines Records exakt zu übertragen, also
Delphi-Quellcode:
anstatt zu sagen:
procedure add( foo: trec );
begin self.arrayoftrec[..].t1 := foo.t1; self.arrayoftrec.t2 := foo.t2; end;
Delphi-Quellcode:
??
...
self.arrayoftrec[...] := foo; ... |
Re: Eigenen Typ in Klasse
Zitat:
mfg Christian |
Re: Eigenen Typ in Klasse
Moin arbu man,
wobei man aus Performance Gründen nicht gerade immer um 1 erhöhen sollte. Erst einmal auf die zu erwartende Grösse setzen, und beim Hinzufügen prüfen, ob noch Platz ist, dann ggf. um einen bestimmten Wert erhöhen. Beim Vergrössern mittels SetLength wird jedesmal ein neues Array angelegt, und der Inhalt des alten dort hineinkopiert. |
Re: Eigenen Typ in Klasse
Auf jeden Fall sollte man nur die gültigen Elemente des Arrays benutzen:
Delphi-Quellcode:
Gruß Hawkeye
procedure tetc.add(foo: Tdeinrecord);
begin setlength(derarray, length(derarray)+1) derarray[High(derarray)]:= foo; // <-- High() statt Length() end; |
Re: Eigenen Typ in Klasse
Zitat:
noch viel besser ist es, hier einfach gar kein Array zu verwenden. Ein Array ist nun mal eine recht statische Struktur und
Delphi-Quellcode:
ist nicht wirklich empfehlenswert (kostet unnötig Zeit und wird vom Speichermanager nicht unbedingt optimal gelöst). Viel besser ist es, wenn du einfach eine TList verwendest, die ist genau dafür gedacht. An sich kannst du deine Records viel schöner als Pointer auf den Record übergeben (ist schneller) und diesen Pointer kannst du dann in deiner TList speichern. Wenn du lesend auf das Array zugreifst, dann kannst du hier ganz einfach eine Methode anlegen, die die TList in ein Array umwandelt. Schreibend kannst du auch Wahlfrei auf die TList zugreifen.
setLength(Array, length(Array) + 1);
Gruß Der Unwissende |
Re: Eigenen Typ in Klasse
Zitat:
mfg Christian |
Re: Eigenen Typ in Klasse
Danke für die vielen Antworten!
Sehe ich das richtig, dass ich mein Problem am besten mit einer Verketteten Liste löse. Da ich aber noch nie viel mit Pointern gearbeitet habe werde ich sicher noch ein paar Fragen an euch haben. Bitte habt ein bisschen Geduld. ;) grz zer00 |
Re: Eigenen Typ in Klasse
Zitat:
Du fährst aber definitiv besser wenn du deine Daten als Instanzen von Klassen abbildest. Records/Structs haben ihre Berechtigungen IMHO nur, wenn man mit einem Speicherbereich fixer Größe arbeiten muss, der in fest vorgechriebene Felder unterteilt wird. Zum Beispiel für API calls. Eine Instanz einer Klasse kostet dich eigentlich nur ihren VMT-Pointer als Overhead, dafür gewinnst du neben Polymorphie noch einiges an Unterstützung des Compilers. ;) |
Re: Eigenen Typ in Klasse
Zitat:
|
Re: Eigenen Typ in Klasse
Zitat:
Ich hoffe ich habe das in etwa richtig gemacht. Code Form1
Delphi-Quellcode:
implementation
uses Termin; {$R *.dfm} var Liste: TList; index: integer; procedure TForm1.NewItem(name, nr: String); begin Liste.Add(TTermin.Create(name,nr)); Label2.Caption:= IntToStr(index); end; procedure TForm1.FormCreate(Sender: TObject); begin Liste:= TList.Create; index:= 0; end; procedure TForm1.Button1Click(Sender: TObject); var name, nr: string; begin name:= Edit1.Text; nr:= Edit2.Text; NewItem(name,nr); end; procedure TForm1.Button2Click(Sender: TObject); begin Edit1.Text:= TTermin(Liste[index]).name; Edit2.Text:= TTermin(Liste[index]).nr; end; procedure TForm1.Button3Click(Sender: TObject); begin Edit1.Clear; Edit2.Clear; end; procedure TForm1.Button5Click(Sender: TObject); begin if(index < Liste.Count -1) then inc(index); Label2.Caption:= IntToStr(index); self.Button2.Click; end; procedure TForm1.Button4Click(Sender: TObject); begin if(index > 0) then dec(index); Label2.Caption:= IntToStr(index); Self.Button2.Click; end; Code der Klasse
Delphi-Quellcode:
Jetzt ist mir einfach nicht ganz klar wie ich die Instanzen wieder freigebe, reicht es wenn ich alle Objects in meiner Liste mit Free freigebe und anschliessend die Liste selbst mit Free freigebe?
unit Termin;
interface type TTermin = class(TObject) private { Private-Deklarationen } FName: String; FNr: String; public { Public-Deklarationen } property Name: String read FName write FName; property nr: String read FNr write FNr; Constructor Create(Name, nr: String); end; implementation Constructor TTermin.Create(Name, nr: String); begin inherited Create; FName:= Name; FNr:= nr; end; end. grz zer00 |
Re: Eigenen Typ in Klasse
Hallo zer00,
wenn du statt einer TList eine ![]()
Delphi-Quellcode:
Wenn du dieser Klasse weitere Methoden spendierst (z.B. LoescheTermin), dann kannst du die gesamte Verwaltung der Termine dort kapseln.
// uses Contnrs;
type TTerminListe = class (TObjectList) private function GetTermin (aIndex: Integer): TTermin; public function NeuerTermin (const aName, aNr: string): TTermin; property Termin [aIndex: Integer]: TTermin read GetTermin; Default; end; function TTerminListe.GetTermin (aIndex: Integer): TTermin; begin Result := TTermin(Items[aIndex]); end; function TTerminListe.NeuerTermin (const aName, aNr: string): TTermin; begin Result := TTermin.Create(aName, aNr); Add(Result); end; Die Verwendung in deinem Programm könnte etwas so aussehen:
Delphi-Quellcode:
Noch eine Bemerkung zu den Prozeduren 'Button4Click' und 'Button5Click': du weißt hoffentlich, daß immer nur eine Anweisung von einem IF abhängt. Wenn alle drei Anweisungen nur im True-Fall ausgeführt werden sollen, dann mußt du sie mit BEGIN..END klammern:
var Liste : TTerminListe;
procedure TForm1.Button2Click(Sender: TObject); begin Edit1.Text := Liste[index].Name; Edit2.Text := Liste[index].nr; end;
Delphi-Quellcode:
Du solltest den Controls auf deinem Formular übrigens aussagekräftigere Namen geben, dann muß man nicht raten, was die einzelnen Routinen bewirken. :wink:
if(index > 0) then
begin dec(index); Label2.Caption:= IntToStr(index); Self.Button2.Click; end; Gruß Hawkeye |
Re: Eigenen Typ in Klasse
Zitat:
Ich werde versuchen deine Tips umzusetzen. Ja ich weiss, dass nur eine Anweisung von IF abhängt. Ich werde versuchen meine Controls besser zu benennen. ;) Und noch einmal vielen Dank! grz zer00 |
Re: Eigenen Typ in Klasse
@ Hawkeye
Ich habe da noch ne Frage bezüglich der ObjectList, ich muss aus zwei Forms auf die Liste zugreiffen, wie mache ich das? grz zer00 |
Re: Eigenen Typ in Klasse
Deklarier die ObjectList public oder nimm zur Not ne globale Deklaration(nicht so schön).
mfg Christian P.S.: ggf. solltest du dazu n neues Thema aufmachen. Zugegeben grenzwertig, aber man könnte das auch als neue Frage auffassen... |
Re: Eigenen Typ in Klasse
Zitat:
|
Re: Eigenen Typ in Klasse
Danke für die Antworten.
Jetzt habe ich es so gelöst. Ich habe eine Klasse TKalender, die für die Anzeige von Tages-, Wochen-, Monatsansicht so wie für die auslösung von Terminen und das verwalten der ObjectList verantwortlich ist. Jetzt habe ich in Form1(Mainform) eine Objectvarible von Typ TKalender erzeugt. Wenn ich jetzt aus Form2 in die ObjectList schreiben will rufe ich Form1.Kalender.Liste.NeuerTermin(); auf. Ist das in etwa richtig? (Bitte seid ein bisschen geduldig mit mir ;) ) grz zer00 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:35 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