Reputation: 371
I try to build a generic class (f.e. a Set- Class). This class should have a function "AsString". But in it i need to typecast to string. How to declare this typecast?
Short Code:
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;
I need a way to typecast FList[i] to string for every "known" special type (of course: each type needs its own operator overloading). something like
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;
Any Idea?
Upvotes: 0
Views: 445
Reputation: 371
Thanks to David Heffernan and Abelisto. Maybe I did not explain the problem as good as possible, but I got the answers I needed. You see the code of an generic Set- class with 3 specializations: integer, double, TestRecord. I shortened it as much as I could.
It works fine (combination operator overloading and generics). Hope, it helps anyone more than only me.
unit 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.
This is not perfect at all, it only shall show the answer to the question: How can I operator overloading if I want develop generic classes. Any hints to improvement are very welcome.
Upvotes: 2