拉撒路:仿制药的类型超载

时间:2017-05-31 13:06:35

标签: operator-overloading lazarus freepascal

我尝试构建一个泛型类(例如,一个Set-Class)。这个类应该有一个函数“AsString”。但在其中我需要对字符串进行类型转换。 如何声明此类型转换?

短代码:

  generic TSet<_T> = class
  private
    FList: array of _T;
  public
    function AsString:string;
  end;

  TSetDouble = specialize TSet<double>;  

function TSet.AsString: string;
var i:integer;
begin
  result := '';
  for i := 0 to Length(FList) - 1 do
    result := result + IntToStr(i) + ' ' + string (FList[i]) + #13#10;
end; 

我需要一种方法将FList [i]强制转换为每个“已知”特殊类型的字符串(当然:每种类型都需要自己的运算符重载)。

之类的东西
operator string(const X:integer):string;
begin result := IntToStr(x);end;

operator string(const X:TMyRecord):string;
begin result := IntToStr(MyRecord.Number) + MyRecord.Text;end;

任何想法?

1 个答案:

答案 0 :(得分:2)

感谢David Heffernan和Abelisto。 也许我没有尽可能好地解释问题,但我得到了我需要的答案。您将看到具有3个特化的泛型Set类的代码:integer,double,TestRecord。我尽可能地缩短了它。

它工作正常(组合运算符重载和泛型)。 希望,除了我之外,它对任何人都有帮助。

单位uSet;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

type

  TTestRecord = record
    i:integer;
    t:string;
    x:double;
  end;

  { TSet }

  generic TSet<_T> = class
  private
    FList: array of _T;
    function GetCount: integer;
    function GetItem(const pcnIndex: integer): _T;
    procedure SetItem(const pcnIndex: integer; const pcItem: _T);
  public
    function FindElement(lvI: _T):integer;
    procedure AddItem(lvI: _T);
    procedure DelItem(lvI: _T);
    property Count:integer read GetCount;
    property Item[const pcnIndex:integer]:_T read GetItem write SetItem;default;
    function IsElement(lvI: _T):boolean;
    function AsString:string;
    constructor Create;
    Destructor Destroy;override;
  end;

  TSetString = specialize TSet<string>;
  TSetDouble = specialize TSet<integer>;
  TSetTestRecord = specialize TSet<TTestRecord>;

implementation

//this operator is needed in function FindElement
operator = (const pcR1, pcR2 : TTestRecord) : boolean;begin result := (pcR1.i=pcR2.i) and (pcR1.t=pcR2.t) and (pcR1.x=pcR2.x); end;

//this operator is needed in function AsString
operator explicit (const pcR1 : TTestRecord) : string;begin result := pcR1.t;end;
operator explicit (const X : integer) : string; begin result := inttostr(X);end;
operator explicit (const d : double) : string;begin result := FloatToStr(d) ;end;

{ TSet }

function TSet.GetCount: integer;
begin
  result := length(FList);
end;

function TSet.GetItem(const pcnIndex: integer): _T;
begin
  if (0 <= pcnIndex) and (pcnIndex < length(FList)) then
    result := FList[pcnIndex]
  else
    raise Exception.Create(Format('Index nicht im gültigen Bereich (0<=%d<%d)',[pcnIndex, length(FList)]));
end;

procedure TSet.SetItem(const pcnIndex: integer; const pcItem: _T);
begin
  if (0 <= pcnIndex) and (pcnIndex < length(FList)) then
    FList[pcnIndex] := pcItem
  else
    raise Exception.Create(Format('Index nicht im gültigen Bereich (0<=%d<%d)',[pcnIndex, length(FList)]));
end;

function TSet.FindElement(lvI: _T): integer;
var i:integer;
begin
  result := -1;
  for i := 0 to length(FList) - 1 do
    if lvI = FList[i] then begin
      result := i;
      break;
    end;
end;

procedure TSet.AddItem(lvI: _T);
begin
  if FindElement(lvI) = -1 then begin
    SetLength(FList,length(FList)+1);
    FList[length(FList)-1] := lvI;
  end;
end;

procedure TSet.DelItem(lvI: _T);
var i, lvnIndex:integer;
begin
  lvnIndex := FindElement(lvI);
  if  lvnIndex > -1 then begin
    for i:=lvnIndex to Length(FList)-2 do
      FList[i]:=FList[i+1];
    SetLength(FList,length(FList)-1);
  end;
end;

function TSet.IsElement(lvI: _T): boolean;
begin
  result := FindElement(lvI) > -1;
end;

function TSet.AsString: string;
var i:integer;
begin
  result := '';
  for i := 0 to Length(FList) - 1 do
    result := result + IntToStr(i) + ' ' + string(FList[i]) + #13#10;
end;

constructor TSet.Create;
begin
  inherited Create;
  SetLength(FList,0);
end;

destructor TSet.Destroy;
begin
  SetLength(FList,0);
  inherited Destroy;
end;

end.

这根本不完美,它只会显示问题的答案:如果我想开发泛型类,我怎么能操作符重载。任何改进的提示都是非常受欢迎的。