![]() |
for...in...do für eine existierende Klasse erstellen
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
in diesem Tutorial möchte ich Euch zeigen, wie man in Delphi 2005 eine Klasse mit der Möglichkeit ausrüstet um das Konstrukt for ... in ... do zu unterstützen. Ähnliches habe ich Euch bereits für ![]() Nehmen wir als Beispiel die einfache Klasse ![]()
Delphi-Quellcode:
Dieses Konstrukt ist zwar korrent, aber es wäre ja doch schön for...in...do zu nutzen. Damit eine Klasse Ihre einzelnen Elemente in einer for...in...do Schleife zurückliefern kann, muss diese die Methode GetEnumerator zur Verfügung stellen. Die Methode muss eine neue Objekt erstellen, welches dann das Objekt mit den zu enumerierenden Elementen durchläuft und die Elemente einzeln zurückliefert.
procedure TForm1.Button1Click(Sender: TObject);
var Sprache: TLanguages; I: Integer; begin Memo1.Clear; Sprache := TLanguages.Create; try for I := 0 to Pred(Sprache.Count) do Memo1.Lines.Add(Sprache.Name[I]); finally Sprache.Free; end; end; In der Delphi 2005 Hilfe: ms-help://borland.bds3/bds3guide/html/DeclarationsAndStatements.htm Wollen wir dieses also für die Klasse TLanguages tun. Damit wir nicht die RTL von Delphi neu kompilieren müssen, werden wir eine neue Unit erstellen, welche eine ![]()
Delphi-Quellcode:
TLanguagesEnum bietet eigentlich nur zwei Methoden. GetCurrent liefert das aktuelle Item (also die Sprache) zurück und MoveNext wählt das nächste Item aus. MoveNext liefert True zurück, wenn ein weiteres Item ausgewählt werden konnte, ansonsten False.
type
TLanguagesEnum = class private FIndex: Integer; FLanguages: TLanguages; public constructor Create(aLanguages: TLanguages); function GetCurrent: String; function MoveNext: Boolean; property Current: String read GetCurrent; end; TLanguagesEx = class helper for TLanguages public function GetEnumerator: TLanguagesEnum; end; Die Implementierung ist denkbar einfach:
Delphi-Quellcode:
Jetzt können wir unsere Methode zum Auslesen der Sprachen wie folgend umstellen:
{ TLanguagesEnum }
constructor TLanguagesEnum.Create(aLanguages: TLanguages); begin inherited Create; FLanguages := aLanguages; FIndex := -1; end; function TLanguagesEnum.MoveNext: Boolean; begin Result := FIndex < Pred(Languages.Count); if Result then Inc(FIndex); end; function TLanguagesEnum.GetCurrent: String; begin Result := Languages.Name[FIndex]; end; { TLanguagesEx } function TLanguagesEx.GetEnumerator: TLanguagesEnum; begin Result := TLanguagesEnum.Create(Self); end;
Delphi-Quellcode:
Klar, für dieses Beispiel mag der Aufwand etwas übertrieben sein, allerdings ist das Beispiel sehr einfach zu verstehen, ausserdem wollte Flosse wissen wie das nun eigentlich geht.
procedure TForm1.Button1Click(Sender: TObject);
var Sprache: TLanguages; Lang: String; begin Memo1.Clear; Sprache := TLanguages.Create; try for Lang in Sprache do begin Memo1.Lines.Add(Lang); end; finally Sprache.Free; end; end; Im Anhang ist die ganze Lösung als Download. ...:cat:... Änderung: Delphi Win32 unterstützt ![]() |
Re: for...in...do für eine existierende Klasse erstellen
Hai Felli *g*
danke für die schöne Erklärung. Sehe ich das jetzt richtig das es pro Klasse nur eine Eigenschaft geben kann die über einen Enumerator angesprochen werden kann? Im Falle von TLanguages könnte ich also nicht sowohl .Name als auch .ID verwenden? |
Re: for...in...do für eine existierende Klasse erstellen
Zitat:
...:cat:... |
Re: for...in...do für eine existierende Klasse erstellen
Ich weiß nicht, wie das in Delphi.NET gehandhabt wird (sowas fasse ich nicht an :mrgreen:), aber wäre es nicht besserer Coding Style, wenn man die Enumerator-Klasse auch explizit als Implementierung von
![]() ![]() Mir fehlt die Syntax dafür, von Delphi/Win32 ausgehend etwas wie
Delphi-Quellcode:
Edit: System.Collections in dem Fall natürlich nicht vergessen :zwinker:
TLanguagesEnum = class(IEnumerator)
|
Re: for...in...do für eine existierende Klasse erstellen
Oben haben wir aber eine Win32-Lösung, keine .NET Lösung und da kannst Du für den Enumerator keine Interfaces nutzen, sondern Du musst eine Klasse nutzen.
...:cat:... |
Re: for...in...do für eine existierende Klasse erstellen
:wall: Da gibt's schon extra verschiedene Icons dafür und dann sowas... :roll:
|
Re: for...in...do für eine existierende Klasse erstellen
An alle, die sich das schon gesaugt haben, holt Euch die neue Version. Ich habe gerade gelernt, dass class helpers auch für Delphi Win32 zur Verfügung stehen, obwohl die Hilfe anderes sagt. Damit ist die neue Lösung natürlich viel eleganter und leichter zu handhaben :firejump:
...:cat:... |
Re: for...in...do für eine existierende Klasse erstellen
Zitat:
Für D7 nutze ich in meinen "Templates" ein GetIEnumerator, das GetEnumerator ist erst mit erfülltem {$IFDEF COMPILER9_UP} sichtbar. ;) (Ich will mich ja unter D7 nicht vertippen und ein MemLeak riskieren :shock: ) Da ich ein Anhänger von Listen bin ist sowas auch unter D7 eine Erleichterung. ;)
Delphi-Quellcode:
Auf die Art kann sich dann der Enum durch die interne Liste hangeln ohne, dass ich damit genervt werde. :)
with SomeCollection.GetIEnumerator() do
while MoveNext() do begin Current.Member := SomeValue; end; |
Re: for...in...do für eine existierende Klasse erstellen
Zitat:
hast du deine "Templates" irgendwo veröffentlicht? Oder is das verschluß sache? ...wär doch toll wenn wir auch was davon haben :-D grüsse. |
Re: for...in...do für eine existierende Klasse erstellen
Ich kann dir ja mal meine Version deines dpCollection templates schicken. ;)
Du kannst sie dann korrekturlesen, veröffentlichen, verbieten, whatever... :mrgreen: Meine listenbasierte Collection ist noch nicht hübsch genug und der Serializer gefällt mir noch überhaupt nicht :? . (Ich komme leider nicht allzu oft dazu mit Delphi rumzuspielen :( ) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:26 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