Zitat von
yankee:
Delphi-Quellcode:
Isin = interface
procedure sin(const arg: extended);
end;
Icos = interface
procedure cos(const arg: extended);
end;
...
TMyClass =class(Icos, Isin, ...)
procedure cos(const arg: extended);
procedure sin(const arg: extended);
...
end;
function callMyFunc(name: string)
begin
//und jetzt? Ich will die Funktion mit dem name den ich übergeben habe aufrufen...
//aber wie helfen mir dabei die Interfaces?
end;
Ok, nimm einfach mal die Map, die Du schon hast. Hier kannst Du ja irgendwie ein Tupel aus String und Adresse speichern und zu einem String eine Adresse anfragen (lookup).
Du erzeugst jetzt also erstmal von jedem Interface (bzw. von der implementierenden Klasse) eine Instanz. Ah, seh gerade was Du falsch verstanden hast. Du hast das mit der Anzahl der Klasse und Interfaces etwas vertauscht.
Delphi-Quellcode:
type
IFunction = interface
function doWork(const argument: Extended): TResultType;
end;
// Gut, an der Benennung könnte man arbeiten, aber Du machst das schon!
TCos = class(TInterfacedObject, IFunction)
public
function doWork(const argument: Extended): TResultType;
end;
TSin = class(TInterfacedObject, IFunction)
public
function doWork(const argument: Extended): TResultType;
end;
Gut, wie die zu implementieren sind ist klar. Jetzt kommt die eigentliche Idee, statt Zeiger auf eine Funktion direkt im Dictionary zu speichern, legst Du nun die Interfaces ab. Da ich gerade nicht weiß wie dein Dictionary aufgebaut ist (dass, das Du verwendest) gehe ich der Einfachheit halber einfach von einer Klasse TDictionary aus, der ich mittels add(String, Interface) ein Element hinzufügen kann und die per Lookup(String): Interface mir ein Interface zurück gibt (musst Du dann nur entsprechend anpassen).
Delphi-Quellcode:
// füllen des Dictionary
var buffer: IFunction;
begin
GlobalDict := TDictionary.Create(...);
buffer := TSin.Create;
GlobalDict.Add('sin', buffer);
buffer := TCos.Create;
GlobalDict.Add('cos', buffer);
// ....
end;
// und jetzt das eigentliche Aufrufen:
function callMyFunc(name: string): FunctionResult;
var funcWrapper: IFunction;
begin
funcWrapper := IFunction(GlobalDict.Lookup(name));
result := funcWrapper.doWork(ExtendedArgument);
end;
Hier hast Du also den Vorteil, dass Du ganz unterschiedliche Klassen im Dictionary abspeicherst, die alle das Interface IFunction implentieren. D.h. hier also, dass Du weißt, dass alles was aus dem Dictionary kommt eine Funktion doWork hat (Ergebnis und Funktionsparameter stehen auch fest). So realisiert man z.B. auch Callbacks in Java (da es ja keine andere Möglichkeit gibt). Ich weiß nicht ob Du in Java mal mit Swing gearbeitet hast? Könnte Dich dann an die Ereignis-Benachrichtigung (einen Listener) erinnern.
Hoffe ist etwas klarer wie ich das meinte (und das nicht wieder ein roter Kasten fehlt).