Einzelnen Beitrag anzeigen

Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#9

Re: Methodpointer - wie funktioniert's?

  Alt 3. Feb 2007, 18:58
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).
  Mit Zitat antworten Zitat