Einzelnen Beitrag anzeigen

Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#1

for...in...do für eine existierende Klasse erstellen

  Alt 22. Apr 2005, 13:42
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 Delphi-Referenz durchsuchenTLanguages 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 Delphi-Referenz durchsuchenHelper 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.
Angehängte Dateien
Dateityp: pas ulanguagesex_330.pas (1,0 KB, 18x aufgerufen)
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat