Quote Originally Posted by Alimonster
You could probably take this further - one rocking feature of Delphi is class references ("class of") - for example, TClass. There should be a way to use them (passing in the type of the functor instead of using a case statement on it), though it escapes me at the moment.
Code:
type
  TBinaryFunc = interface(TInterfacedObject, IBinaryFunc) 
    Constructor create; virtual;   
    function DoIt(X,Y: Integer): Integer; virtual; abstract;
  end; 
  TBinaryFuncClass = class of TBinaryFunc;
.... 
function DoStuff(Num1, Num2: Integer; OperationClass: IBinaryFuncClass): Integer; 
begin 
  Result := IBinaryFunc(OperationClass.Create).DoIt(Num1, Num2); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  case rgpWhatever.ItemIndex of 
    -1: ; 
     0: ShowMessage(IntToStr(DoStuff(3, 6, TBinaryAdd))); 
     1: ShowMessage(IntToStr(DoStuff(13, 4, TBinarySub))); 
     2: ShowMessage(IntToStr(DoStuff(3, 5, TBinaryMultiply))); 
     3: ShowMessage(IntToStr(DoStuff(12, 4, TBinaryDivide))); 
  end; 
end;
You need the costructor to be virtual, so when you use a class reference it will resolve to the correct constructor.

You can get away with "IBinaryFunc(OperationClass.Create).DoIt" because of 2 reasons:
1) if an exception occurs, the constructor fails and the detsructor is called. Thus the Constructor always returns a valid value, or it raises an exception.
2) IBinaryFunc(OperationClass.Create) makes sure the returned class is treaded as an interface. This will cause the referance count to equal one while DoIt is executing, but as soon as the statement finishes, the reference count is decreased, and the interface freed. You might be able to remove the cast, but I havent compiled that to check to see if that would work.

Also you can have virtual class functions too.
Code:
type
  TBinaryFunc = interface(TInterfacedObject, IBinaryFunc) 
    Constructor create; virtual;
    class function DoIt(X,Y: Integer): Integer; virtual; abstract;
  end;
Then something like "OperationClass.Doit" is valid and will call the correct function.

This is useful in a system when you have a list of class types which you create a new instance of each time you use the class type, but need extra information from each class type but dont want to have to create a new class to contain this information (which is static).

Tobject.ClassName is an example of this.