Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with generics and interfaces and inheritance

The following example is giving me this error:
[DCC Error] Unit2.pas(54): E2010 Incompatible types: 'IBar' and 'Unit2.TFoo<Unit2.IBar>'

I think the problem is somewhere around the Self.Create Because after many tries to get it compiled I accidentally entered FFoo := TBar(Self).Create; and it compiled and worked.

I'm using Delphi XE

IFoo = interface
end;

TFoo<T: IInterface> = class(TInterfacedObject, IFoo)
private class var
  FFoo: T;
public class
  function Instance: T;
end;

IBar = interface(IFoo)
end;

TBar = class(TFoo<IBar>, IBar)
end;

class function TFoo<T>.Instance: T;
begin
  if not Assigned(FFoo) then
  begin
    FFoo := Self.Create;
  end;
  Result := FFoo;
end;
like image 665
RjK Avatar asked Jan 23 '11 22:01

RjK


People also ask

Can generic class be inherited?

You cannot inherit a generic type. // class Derived20 : T {}// NO!

Can we use generics in interface?

Generics make a class, interface and, method, consider all (reference) types that are given dynamically as parameters. This ensures type safety. Generic class parameters are specified in angle brackets “<>” after the class name as of the instance variable. Generic constructors are the same as generic methods.

Do generics increase performance?

Go's generics will almost certainly improve your development and lifetime performance, in raw performance, if generics are used when you actually need them they should also be a performance boost.


2 Answers

The problem is in this line with the TBar declaration:

FFoo := Self.Create;

To understand, let's explain the types behind the code [noted like this]:

FFoo:[IBar] := Self:[TFoo(IBar)].Create():[TFoo<IBar>]

So, tu summarize, we have : [IBar] := [TFoo<IBar>]
Are these types compatible ?
A [TFoo] only implements IFoo interface, no IBar as it is stated in your code

TFoo<T: IInterface> = class(TInterfacedObject, IFoo)

This is the compilation error !
UPDATE : Solution 1
To fix the issue : change the TBar declaration

TBar = class(TFoo<IFoo>, IBar)
end;

UPDATE : Solution 2
Replace the FFoo := Self.Create by

FFoo := Self.Create.Instance;

and so it works !

like image 190
TridenT Avatar answered Nov 15 '22 10:11

TridenT


Your TFoo does not implement T as interface. That's why FFoo and an instance of TFoo is not compatible. If you want to assign an instance of TFoo to FFoo you need to hardcast it.

like image 45
Stefan Glienke Avatar answered Nov 15 '22 10:11

Stefan Glienke