#1 2020-02-14 07:07:08

squirrel
Member
Registered: 2015-08-13
Posts: 146

overload interface functions

What would be the best option to overload an interface function?  I understand that mormot would not know which function to call, so maybe declaring all the parameters as variant?

I need to provide somthing silimar to this (have unfortunately no say in providing as 2 differently named functions - external requirement):

function CountItems(const grouping: string): integer; overload;
function CountItems(const grouping: TStringDynArray): integer; overload;

Would using a plain Variant work? I tried this:

function CountItems(const grouping: Variant): integer;

which works fine for the string, but how would I use that as a TStringDynArray?

Last edited by squirrel (2020-02-14 08:22:22)

Offline

#2 2020-02-14 14:20:05

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: overload interface functions

What if you always accept only an array?

function CountItems(const grouping: TStringDynArray): integer; 
begin
  if Length(grouping) = 1 then 
    ... one string
  else if  Length(grouping)  > 1 then
    ... some strings
end;

If, form some reason, you need to know if it really is an "alone" item to do the proper treatment, you can use an additional parameter ...

function CountItems(const grouping: TStringDynArray; isOneGroup : boolean): integer; 
begin
   if (isOneGroup) and (Length(grouping) = 1) ....
end;

Offline

#3 2020-02-15 11:24:17

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,237
Website

Re: overload interface functions

By design, the method name matches the REST URI, so overlapping method names won't work in the internal router.

A variant would work - if you use a TDocVariant for storing the strings.
But two interfaces, with diverse names, may be better, since it would be less confusing.
Or just a single interface accepting an array, in your case... and let the client make a little more work.

Offline

#4 2020-02-17 06:27:48

squirrel
Member
Registered: 2015-08-13
Posts: 146

Re: overload interface functions

This is why politics and programming should never mix.   In this instance I unfortunately don't have a say in what the client does.  They use an html select dropdown, which can sometimes be a single value and sometimes a multiple select.  While it would take them 10 seconds to ensure an array is always sent, its not happening.

My interim solution to keep the project on track, was to keep the grouping as a Variant, but then internally copy it to an array.  It might not be elegant, but will do for now.  I'm sure there is a more efficient way of doing this.

procedure ParseVariantToArray(const Data: Variant; var Arr: TStringDynArray);
var
  I: Integer;
begin
  SetLength(Arr, 0);
  if (not VarIsEmpty(Data)) and (not VarIsNull(Data)) then
  begin
    if VarIsNumeric(Data) then
      Arr := [FloatToStr(Data)]
    else
    if VarIsStr(Data) then
      Arr := [Data]
    else
      for I := 0 to TDocVariantData(Data).Count -1 do
        Arr := Arr + [TDocVariantData(Data).Value[I]];
  end;
end;

Last edited by squirrel (2020-02-17 06:57:37)

Offline

#5 2020-02-17 09:27:30

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,237
Website

Re: overload interface functions

You should rather use _Safe(Data)^ than TDocVariantData(Data) if the incoming variant has indirection.

Offline

#6 2020-02-17 10:46:04

squirrel
Member
Registered: 2015-08-13
Posts: 146

Re: overload interface functions

cool Thanks ab.  I always forget about _Safe, somehow TDocVariantData(Data) still comes more readable and naturally to me.

Offline

Board footer

Powered by FluxBB