Hi mates,
I have something on my mind but I couldn't implement it correctly, imagine a generic interface, some classes inherited from that interface, and one method in each class with the same name, now I'm trying to use this interface type every where for different approaches but it doesn't compile correctly.
Please have a look at the code if you get a chance and share your thoughts with me, I do appreciate you in advance.
The question is how can I implement such an idea properly and safely?
I have attached a sample project to save you time too.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Rtti;
type
IMyInterface<T> = interface
function DoSomething: T;
end;
TMyClass<T> = class(TInterfacedObject, IMyInterface<T>)
function DoSomething: T;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
function UseInterface<T>(obj: IMyInterface<T>): T;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TMyClass<T> }
function TMyClass<T>.DoSomething: T;
var
ctx: TRttiContext;
typ: TRttiType;
begin
ctx := TRttiContext.Create;
typ := ctx.GetType(TypeInfo(T));
if typ.TypeKind = tkInteger then
Result := 20 // E2010 Incompatible types: 'T' and 'Integer'
else if typ.TypeKind = tkString then
Result := T('Hello') // E2089 Invalid typecast
else
if typ.AsInstance.MetaclassType.InheritsFrom(TStringList) then
Result := (typ.AsInstance.MetaclassType.InitInstance(typ) as TStringList) //E2010 Incompatible types: 'T' and 'TStringList'
else
Result := Default(T);
ctx.Free;
end;
{ TForm1 }
function TForm1.UseInterface<T>(obj: IMyInterface<T>): T;
begin
Result := obj.DoSomething;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
obj1: IMyInterface<Integer>;
obj2: IMyInterface<String>;
obj3: IMyInterface<TStringList>;
begin
try
obj1 := TMyClass<Integer>.Create;
obj2 := TMyClass<String>.Create;
obj3 := TMyClass<TStringList>.Create;
ShowMessage(UseInterface<Integer>(obj1).ToString);
ShowMessage(UseInterface<String>(obj2));
ShowMessage(UseInterface<TStringList>(obj3).Text);
except
on E: Exception do
Writeln('Exception: ', E.ClassName, ': ', E.Message);
end;
end;
end.
Generic Interface.zip