yankee
yankee

Reputation: 509

Delphi: calling a method of a subclass from an Interface reference

I have a set of classes that derive from a base class. The base class represents a generic service to be invoked (actually is a sort of REST client), and each derived class is a wrapper for each specific service (with specific parameters). Note that my base class implements an Interface.

Here is some simplified code:

IMyService = interface
  ['{049FBEBD-97A8-4F92-9CC3-51845B4924B7}']
  function GetResponseContent: String;
  // (let's say AParams is a comma-delimited list of name=value pairs) 
  procedure DoRequest(const AParams: String); overload;  // (1)
  property ResponseContent: String read GetResponseContent; 
end;

TMyBaseService = class(TInterfacedObject, IMyService)
protected
  FResponseContent: String;
  function GetResponseContent: String;
public
  procedure DoRequest(const AParams: String); overload;  // (1)
  property ResponseContent: String; 
end;

TFooService = class(TMyBaseService)
public
  // This specific version will build a list and call DoRequest version (1)
  procedure DoRequest(AFooParam1: Integer; AFooParam2: Boolean); overload; // (2)
end;

TBarService = class(TMyBaseService)
public
  // This specific version will build a list and call DoRequest version (1)
  procedure DoRequest(ABarParam1: String); overload;  // (3)
end;

Now, I can always create and invoke a service in a generic, late-custom-bound way, passing the "open" list of params as in (1) and crossing my fingers:

var
  Foo, Bar: IMyService;
begin
  Foo := TFooService.Create;
  Bar := TBarService.Create;
  Foo.DoRequest('name1=value1,name2=value2'); 
end;

But what's the best way to call the specific DoRequest marked as (2) and (3)?

I can't cast interface reference to object TFooService(Foo).DoRequest(2, False),
and I can't declare Foo: TFooService because I need to use the interface reference for ARC (automatic reference count).

Upvotes: 2

Views: 1141

Answers (1)

David Heffernan
David Heffernan

Reputation: 612963

Make interfaces to represent the other functionality. For instance:

type
  IFooService = interface
    [GUID here]
    procedure DoRequest(AFooParam1: Integer; AFooParam2: Boolean); overload;
  end;

Make TFooService implement it

type
  TFooService = class(TMyBaseService, IFooService)
  ....

Then use as to gain access to it:

var
  Foo: IMyService;
....
(Foo as IFooService).DoRequest(AFooParam1, AFooParam2);

Upvotes: 2

Related Questions