Generics - extending TFPGObjectList

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Generics - extending TFPGObjectList

vojtech.cihak

Hello,

 

I needed to extend TFPGObjectList and I found two wierd things (FPC 3.1.1 r39507):

 

program project1;

{$mode objfpc}{$H+}

 

uses

  Classes, FGL;

 

type

  TBaseClass = class (TObject)

  end;

 

  TIDClass = class (TBaseClass)

    ID: Integer;

  end;

 

  TNameIDClass = class (TIDClass)

    Name: string;

  end;

 

  generic TFPGObjectListEx<T: TIDClass> = class (specialize TFPGObjectList<TBaseClass>) //1 A

    function GetItemByID(AID: Integer): T;

  end;

 

  TNameIDList = class (specialize TFPGObjectListEx<TNameIDClass>)

 

  end;

 

{$R *.res}

 

function TFPGObjectListEx.GetItemByID(AID: Integer): T;

begin

  {...}

  Result:=nil; //2

end;

 

var NameIDList: TNameIDList;

    NameID: TNameIDClass;

begin

  NameID:=NameIDList.Items[0]; //1 B

end.

 

The demo does not compile because of two errors:

1) project1.lpr(38,21) Error: Incompatible types: got "TBaseClass" expected "TNameIDClass" at comment //1 B

It is caused by declaration at //1 A. Class TFPGObjectListEx can be really generic only if it is declared like this:

   generic TFPGObjectListEx<T: TIDClass> = class (specialize TFPGObjectList<T>) //1 A, otherwise you must retype TNameIDClass(Items[0]) and it is against the philosophy of generics. Isn't it meaningless? Why there must be specialize to <T> when in fact it is no specialization at all.

 

2) project1.lpr(32,11) Error: Incompatible types: got "Pointer" expected "$gendef4" at comment //2

The line must be changed to

  Result:=T(nil);

which seems bizarre to me, I've never seen retyping "nil". Even more, both TFPGObjectList and TFPGObjectListEx are constrained to TObject and to TIDClass so there is safety, TFPGObjectListEx can be only specialized with types that have "nil" (<T> can never be <Integer>, for example).

 

Thanks,

 

Vojtěch.

 

PS: The demo crashes.


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Generics - extending TFPGObjectList

Free Pascal - General mailing list
Am 26.07.2018 um 02:31 schrieb Vojtěch Čihák:

Hello,

 

I needed to extend TFPGObjectList and I found two wierd things (FPC 3.1.1 r39507):

 

program project1;

{$mode objfpc}{$H+}

 

uses

  Classes, FGL;

 

type

  TBaseClass = class (TObject)

  end;

 

  TIDClass = class (TBaseClass)

    ID: Integer;

  end;

 

  TNameIDClass = class (TIDClass)

    Name: string;

  end;

 

  generic TFPGObjectListEx<T: TIDClass> = class (specialize TFPGObjectList<TBaseClass>) //1 A

    function GetItemByID(AID: Integer): T;

  end;

 

  TNameIDList = class (specialize TFPGObjectListEx<TNameIDClass>)

 

  end;

 

{$R *.res}

 

function TFPGObjectListEx.GetItemByID(AID: Integer): T;

begin

  {...}

  Result:=nil; //2

end;

 

var NameIDList: TNameIDList;

    NameID: TNameIDClass;

begin

  NameID:=NameIDList.Items[0]; //1 B

end.

 

The demo does not compile because of two errors:

1) project1.lpr(38,21) Error: Incompatible types: got "TBaseClass" expected "TNameIDClass" at comment //1 B

It is caused by declaration at //1 A. Class TFPGObjectListEx can be really generic only if it is declared like this:

   generic TFPGObjectListEx<T: TIDClass> = class (specialize TFPGObjectList<T>) //1 A, otherwise you must retype TNameIDClass(Items[0]) and it is against the philosophy of generics. Isn't it meaningless? Why there must be specialize to <T> when in fact it is no specialization at all.


You are not overriding the Items property, thus it will still be the Items property of TFPGObjectList<TBaseClass> and thus the compiler will rightfully complain at location 1 B. Using generics does not absolve you from usual inheritance problems.

 

2) project1.lpr(32,11) Error: Incompatible types: got "Pointer" expected "$gendef4" at comment //2

The line must be changed to

  Result:=T(nil);

which seems bizarre to me, I've never seen retyping "nil". Even more, both TFPGObjectList and TFPGObjectListEx are constrained to TObject and to TIDClass so there is safety, TFPGObjectListEx can be only specialized with types that have "nil" (<T> can never be <Integer>, for example).

Well, no one said that the generics are completely bug free... Especially in special situations that involve either Nil or type constraints (or in this case both). Please provide a simple example and open a bug report.

Regards,
Sven

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Generics - extending TFPGObjectList

vojtech.cihak
In reply to this post by vojtech.cihak

Thanks for reply.

 

Ad 2) I opened issue: https://bugs.freepascal.org/view.php?id=34037

 

Ad 1) Are there any plans for improvement of generic inheritance? Related to my example, instead of

 

    generic TFPGObjectListEx<T: TIDClass> = class (specialize TFPGObjectList<T>)

 

I would prefer simplier and more straightforward

 

    generic TFPGObjectListEx<T> = class (TFPGObjectList)

 

which will give programmers possibility to extend classes from FGL without any further constraints.

 

What if I fill feature request? :-)

 

Vojtěch

 

______________________________________________________________
> Od: Sven Barth via fpc-pascal <[hidden email]>
> Komu: [hidden email]
> Datum: 26.07.2018 07:04
> Předmět: Re: [fpc-pascal] Generics - extending TFPGObjectList
>

Am 26.07.2018 um 02:31 schrieb Vojtěch Čihák:

Hello,

 

I needed to extend TFPGObjectList and I found two wierd things (FPC 3.1.1 r39507):

 

program project1;

{$mode objfpc}{$H+}

 

uses

  Classes, FGL;

 

type

  TBaseClass = class (TObject)

  end;

 

  TIDClass = class (TBaseClass)

    ID: Integer;

  end;

 

  TNameIDClass = class (TIDClass)

    Name: string;

  end;

 

  generic TFPGObjectListEx<T: TIDClass> = class (specialize TFPGObjectList<TBaseClass>) //1 A

    function GetItemByID(AID: Integer): T;

  end;

 

  TNameIDList = class (specialize TFPGObjectListEx<TNameIDClass>)

 

  end;

 

{$R *.res}

 

function TFPGObjectListEx.GetItemByID(AID: Integer): T;

begin

  {...}

  Result:=nil; //2

end;

 

var NameIDList: TNameIDList;

    NameID: TNameIDClass;

begin

  NameID:=NameIDList.Items[0]; //1 B

end.

 

The demo does not compile because of two errors:

1) project1.lpr(38,21) Error: Incompatible types: got "TBaseClass" expected "TNameIDClass" at comment //1 B

It is caused by declaration at //1 A. Class TFPGObjectListEx can be really generic only if it is declared like this:

   generic TFPGObjectListEx<T: TIDClass> = class (specialize TFPGObjectList<T>) //1 A, otherwise you must retype TNameIDClass(Items[0]) and it is against the philosophy of generics. Isn't it meaningless? Why there must be specialize to <T> when in fact it is no specialization at all.


You are not overriding the Items property, thus it will still be the Items property of TFPGObjectList<TBaseClass> and thus the compiler will rightfully complain at location 1 B. Using generics does not absolve you from usual inheritance problems.

 

2) project1.lpr(32,11) Error: Incompatible types: got "Pointer" expected "$gendef4" at comment //2

The line must be changed to

  Result:=T(nil);

which seems bizarre to me, I've never seen retyping "nil". Even more, both TFPGObjectList and TFPGObjectListEx are constrained to TObject and to TIDClass so there is safety, TFPGObjectListEx can be only specialized with types that have "nil" (<T> can never be <Integer>, for example).

Well, no one said that the generics are completely bug free... Especially in special situations that involve either Nil or type constraints (or in this case both). Please provide a simple example and open a bug report.

Regards,
Sven


----------

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Generics - extending TFPGObjectList

Free Pascal - General mailing list
Vojtěch Čihák <[hidden email]> schrieb am Do., 26. Juli 2018, 13:40:

Thanks for reply.

 

Ad 2) I opened issue: https://bugs.freepascal.org/view.php?id=34037

 

Ad 1) Are there any plans for improvement of generic inheritance? Related to my example, instead of

 

    generic TFPGObjectListEx<T: TIDClass> = class (specialize TFPGObjectList<T>)

 

I would prefer simplier and more straightforward

 

    generic TFPGObjectListEx<T> = class (TFPGObjectList)

 

which will give programmers possibility to extend classes from FGL without any further constraints.

 

What if I fill feature request? :-) 

I have no intention of changing this. 

Regards, 
Sven 


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal