<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="moz-cite-prefix">Am 26.07.2018 um 02:31 schrieb Vojtěch
Čihák:<br>
</div>
<blockquote type="cite" cite="mid:20180726023153.4044CD7C@atlas.cz">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<p style="padding:0 0 0 0; margin:0 0 0 0;">Hello,</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">I needed to
extend TFPGObjectList and I found two wierd things (FPC 3.1.1
r39507):</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">program project1;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">{$mode objfpc}{$H+}</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">uses</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> Classes, FGL;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">type</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> TBaseClass = class
(TObject)</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> end;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> TIDClass = class
(TBaseClass)</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> ID: Integer;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> end;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> TNameIDClass = class
(TIDClass)</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> Name: string;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> end;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> generic
TFPGObjectListEx<T: TIDClass> = class (specialize
TFPGObjectList<TBaseClass>) //1 A</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> function
GetItemByID(AID: Integer): T;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> end;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> TNameIDList = class
(specialize TFPGObjectListEx<TNameIDClass>)</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> end;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">{$R *.res}</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">function
TFPGObjectListEx.GetItemByID(AID: Integer): T;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">begin</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> {...}</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> Result:=nil; //2</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">end;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">var NameIDList:
TNameIDList;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> NameID:
TNameIDClass;</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">begin</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">
NameID:=NameIDList.Items[0]; //1 B</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">end.</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">The demo does not
compile because of two errors:</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"><span
style="font-size: 10pt;">1) </span>project1.lpr(38,21) Error:
Incompatible types: got "TBaseClass" expected "TNameIDClass" at
comment //1 B</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">It is caused by
declaration at //1 A. Class <span style="font-size: 13.3333px;">TFPGObjectListEx
can be really generic only if it is declared like this:</span></p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> generic
TFPGObjectListEx<T: TIDClass> = class (specialize
TFPGObjectList<T>) //1 A, otherwise you must retype <span
style="font-size: 13.3333px;">TNameIDClass(</span><span
style="font-size: 10pt;">Items[0]) and it is against the
philosophy of generics. I</span><span style="font-size: 10pt;">sn't
it meaningless? Why there must be specialize to <T> when
in fact it is no specialization at all.</span></p>
</blockquote>
<br>
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.<br>
<br>
<blockquote type="cite" cite="mid:20180726023153.4044CD7C@atlas.cz">
<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">2) project1.lpr(32,11)
Error: Incompatible types: got "Pointer" expected "$gendef4" at
comment //2</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">The line must be
changed to</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;"> Result:=T(nil);</p>
<p style="padding:0 0 0 0; margin:0 0 0 0;">which seems bizarre to
me, I've never seen retyping "nil". Even more, both <span
style="font-size: 13.3333px;">TFPGObjectList and </span><span
style="font-size: 13.3333px;">TFPGObjectListEx are constrained
to TObject and to TIDClass so there is safety, </span><span
style="font-size: 13.3333px;">TFPGObjectListEx can be only
specialized with types that have "nil" (<T> can never be
<Integer>, for example).</span></p>
</blockquote>
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.<br>
<br>
Regards,<br>
Sven<br>
</body>
</html>