13 Stimmen

Übergabe der Methode der Schnittstelle als Parameter

Ist es möglich, die Methode der Schnittstelle als Parameter zu übergeben?

Ich versuche etwas in dieser Richtung:

interface

type
  TMoveProc = procedure of object;
  // also tested with TMoveProc = procedure;
  // procedure of interface is not working ;)

  ISomeInterface = interface
    procedure Pred;
    procedure Next;
  end;

  TSomeObject = class(TObject)
  public
    procedure Move(MoveProc: TMoveProc);
  end;

implementation

procedure TSomeObject.Move(MoveProc: TMoveProc);
begin
  while True do
  begin
    // Some common code that works for both procedures
    MoveProc;
    // More code...
  end;
end;

procedure Usage;
var
  o: TSomeObject;
  i: ISomeInterface;
begin
  o := TSomeObject.Create;
  i := GetSomeInterface;
  o.Move(i.Next);
  // somewhere else: o.Move(i.Prev);
  // tested with o.Move(@i.Next), @@... with no luck
  o.Free;
end;

Aber es funktioniert nicht, weil:

E2010 Inkompatible Typen: 'TMoveProc' und 'Prozedur, nicht typisierter Zeiger oder nicht typisierter Parameter'

Natürlich kann ich für jeden Aufruf eine private Methode verwenden, aber das ist unschön. Gibt es einen besseren Weg?

Delphi 2006


Bearbeiten: Ich weiß, dass ich ganze Schnittstelle übergeben kann, aber dann muss ich angeben, welche Funktion verwenden. Ich möchte nicht zwei exakt gleiche Prozeduren mit einem unterschiedlichen Aufruf.

Ich kann den zweiten Parameter verwenden, aber auch das ist hässlich.

type
  SomeInterfaceMethod = (siPred, siNext)

procedure Move(SomeInt: ISomeInterface; Direction: SomeInterfaceMethod)
begin
  case Direction of:
    siPred: SomeInt.Pred;
    siNext: SomeInt.Next
  end;
end;

Vielen Dank für alle Hilfe und Ideen. Die saubere Lösung (für mein Delphi 2006) ist Diegos Visitor. Jetzt bin ich mit einfachen ("hässlich") Wrapper (meine eigene, gleiche Lösung von TOndrej und Aikislave).

Aber die wahre Antwort lautet: "Es gibt keine (direkte) Möglichkeit, die Methoden der Schnittstelle als Parameter zu übergeben, ohne eine Art von Anbieter.

1voto

yonojoy Punkte 5298

Hier ist eine weitere Lösung, die in Delphi 20006 funktioniert. Sie ist ähnlich wie die Idee von @Rafael, verwendet aber Schnittstellen:

interface 

type
  ISomeInterface = interface
    //...
  end;

  IMoveProc = interface
    procedure Move;
  end;

  IMoveProcPred = interface(IMoveProc)
  ['{4A9A14DD-ED01-4903-B625-67C36692E158}']
  end;

  IMoveProcNext = interface(IMoveProc)
  ['{D9FDDFF9-E74E-4F33-9CB7-401C51E7FF1F}']
  end;

  TSomeObject = class(TObject)
  public
    procedure Move(MoveProc: IMoveProc);
  end;

  TImplementation = class(TInterfacedObject, 
      ISomeInterface, IMoveProcNext, IMoveProcPred)
    procedure IMoveProcNext.Move = Next;
    procedure IMoveProcPred.Move = Pred;
    procedure Pred;
    procedure Next;
  end;

implementation

procedure TSomeObject.Move(MoveProc: IMoveProc);
begin
  while True do
  begin
    // Some common code that works for both procedures
    MoveProc.Move;
    // More code...
  end;
end;

procedure Usage;
var
  o: TSomeObject;
  i: ISomeInterface;
begin
  o := TSomeObject.Create;
  i := TImplementation.Create;
  o.Move(i as IMoveProcPred);
  // somewhere else: o.Move(i as IMoveProcNext);
  o.Free;
end;

-1voto

mj2008 Punkte 6597

Sie haben derzeit TMoveProc definiert als

TMoveProc = procedure of object;

Versuchen Sie, das "of object" herauszunehmen, das einen versteckten "this"-Zeiger als ersten Parameter impliziert.

TMoveProc = procedure;

Damit sollte ein normales Verfahren aufgerufen werden können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X