user1009073
user1009073

Reputation: 3238

Delphi - How to return different types from a function

Delphi Rio - I am writing a class, where one of the functions is AddFilter. When the AddFilter class is executed, depending on various factors it will either create a filter, or create a slicer. (Think of Excel Filters and Slicers). I want the function to return the newly created object, which is either tFilterElement, or tSlicerElement, which are separate, non-related classes. My challenge is how do I have a function which can return a newly created object; which can be one of 2 different classes? I am trying to use Variants here, but I cannot get this to work. Pseudo Code is

function TPivotTable.addFilter(params...):Variant;
var
E1 : tFilterElement;
E2 : tSlicerElement;

begin

... if this can be a Filter
E1 := TFilterElement.Create(params);
result := E1;

... else
E2 := TSlicerElement.Create; 
result := E2;
 
end;

I have tried

result := E1 as Variant;

as well as

result := Variant(E1);

But neither work. Is there a way to do this? I am not tied to Variants, I just couldn't think of any other approach that might work.

Upvotes: 2

Views: 845

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 108929

You can always declare the result type as TObject, or any other common ancestor of both TFilterElement and TSlicerElement:

function TPivotTable.AddFilter(...): TObject;
begin
  if SomeCondition then
    Result := TFilterElement.Create
  else
    Result := TSlicerElement.Create;
end;

When you use this function, you must then investigate the result and see what class it is:

MyThing := MyPivotTable.AddFilter(...);
if MyThing is TFilterElement then
  TFilterElement(MyThing).DoSomeFilterStuff
else if MyThing is TSlicerElement then
  TSlicerElement(MyThing).DoSomeSlicerStuff
else
  raise Exception.Create('Neither a filter nor a slicer was returned.');

All this being said, this seems like a rather poor design. (All is checks and casting is a sign of this.)

I don't know your application, but maybe you could create a class TElement with TFilterElement and TSlicerElement as descendant classes?

Upvotes: 4

Related Questions