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
COM Collectionen gezeigt.
Nehmen wir als Beispiel die einfache Klasse
TLanguages aus der
Unit SysUtils heran. Diese Klasse unterstützt das neue Loop-Konstrukt aus Delphi leider nicht. Um alle unterstützten Sprachen zu ermitteln muss man normalerweise folgendes nutzen:
Delphi-Quellcode:
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;
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.
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
Helper Class für TLanguages bietet und für diese den Enumerator zur Verfügung stellt. Das Interface ist recht einfach:
Delphi-Quellcode:
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;
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.
Die Implementierung ist denkbar einfach:
Delphi-Quellcode:
{ 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;
Jetzt können wir unsere Methode zum Auslesen der Sprachen wie folgend umstellen:
Delphi-Quellcode:
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;
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.
Im Anhang ist die ganze Lösung als Download.
...

...
Änderung: Delphi
Win32 unterstützt
class helpers, die Hilfe sagt die sind nur für Delphi.NET. Sample entsprechend angepasst.