我尝试构建一个泛型类(例如,一个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;
任何想法?
答案 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.
这根本不完美,它只会显示问题的答案:如果我想开发泛型类,我怎么能操作符重载。任何改进的提示都是非常受欢迎的。