Hallo zusammen!
[Übersetzung meines englischen
Announcements]
Es freut mich endlich bekannt geben zu können, dass Free Pascal nun generische Funktionen, Prozeduren und Methoden (zusammengefasst "Routinen") unterstützt, wodurch es möglich wird typsichere Routinen zu schreiben, die für mehrere Typen verwendet werden können.
Syntax:
Die Syntax zum Deklarieren einer generischen Routine gleicht der für normale Routinen und beinhaltet auch die Unterstützung für Klassenmethoden:
Delphi-Quellcode:
generic [class] (procedure|function) IDENTIFIER<TYPEARGLIST>[(PARAMETERLIST)][: RESULTTYPE]; MODIFIERS;
Für die
TYPEARGLIST gelten die gleichen Regeln wie für generische Typen. Typparameter, die in der
TYPEARGLIST deklariert sind können in der
PARAMETERLIST, dem
RESULTTYPE und natürlich dem Routinenkörper verwendet werden.
Generische Routinen können sowohl durch die
TYPEARGLIST, als auch durch die
PARAMETERLIST überladen werden.
Um eine generische Routine aufzurufen wird die folgende Syntax verwendet:
Delphi-Quellcode:
specialize IDENTIFIER<TYPELIST>[(PARAMETERS)]
Für die
TYPELIST gelten die gleichen Regeln wie beim Spezialisieren eines generischen Typen.
Falls die Routine Teil eines Typs oder einer Variable ist oder ein Unitname zum Zweck der Eindeutigkeit verwendet wird, dann muss dieser Teil vor dem
specialize
kommen:
Delphi-Quellcode:
TYPENAME.specialize IDENTIFIER<TYPELIST>[(PARAMETERS)]
VARIABLE.specialize IDENTIFIER<TYPELIST>[(PARAMETERS)]
UNITNAME.specialize IDENTIFIER<TYPELIST>[(PARAMETERS)]
Aufrufe von generischen Routinen sind normale Faktoren, wodurch sie auch als solche genutzt werden können, wie das folgende Beispiel zeigt:
Delphi-Quellcode:
{$mode objfpc}
generic function Add<T>(aLeft, aRight: T): T;
begin
Result := aLeft + aRight;
end;
begin
Writeln(specialize Add<String>('Generic ', 'routines') + specialize Add<String>(' with ', 'Free Pascal'));
end.
Delphikompatibilität:
Natürlich ist dieses Feature für die Delphi modes auch delphikompatibel implementiert. Dort ist die Syntax zum Deklararien einer generischen Routine wie folgt:
Delphi-Quellcode:
[class] (procedure|function) IDENTIFIER<TYPELIST>[(PARAMETERLIST)][: RETURNTYPE]; MODIFIERS;
Es fehlt also nur das
generic
Schlüsselwort. Dies ist analog beim Aufruf einer generischen Routine:
Delphi-Quellcode:
IDENTIFIER<TYPELIST>[(PARAMETERS)]
Auf Grund des fehlenden
specialize
Schlüsselwortes das Spezialisierungen markiert funktionieren komplexe Ausdrücke
noch nicht in den Delphi Modi. Das heißt, dass die Zuweisung von Rückgabewerten okay ist, aber mit mehr als das ist es sehr möglich auf Compilerfehler zu stoßen.
Bitte beachtet, dass im Gegensatz zu Delphi von uns globale generische Funktionen/Prozeduren auch im Delphi Modus unterstützt werden.
Einschränkungen/ToDos:
Dieses Feature ist noch nicht vollständig and es gibt einige Einschränkungen, die noch überwunden werden müssen oder Teile die noch nicht funktionieren. Dies beinhaltet, ist aber nicht beschränkt auf:
- Unterstützung für komplexe Ausdrücke in den Delphi Mode (betrifft auch Typspezialisierungen)
- Unterstützung für Zeiger auf generische Routinen (im besten Fall endet das aktuell in Fehlermeldungen, im schlechtesten in internen Fehlern oder Exceptions)
- Unterstützung für Rückgabevariablen in Modi, die Result
nicht unterstützen
- Unterstützung für verschachtelte Generics, am wichtigsten generische Methoden in generischen Klassen
Bitte testet dieses Feature and meldet alle Probleme im
Bug Tracker. Fragen können natürlich auch hier im Forum (oder auf der Mailing Liste) gestellt werden (nein, dieses Feature wird nicht Teil von 3.0.0 sein).
Schöne Grüße,
Sven