A Generic Inheriting a Generic in a Generic Way - 2 lazarus / 64-FPC development ---------------------------------------------------------------------- IndigoBoy83 · 2015-02-20 21:12 - THIS IS A CONTINUATION OF THE PREVIOUS POST - A Generic Inheriting a Generic in a Generic Way - 1 ------ Now, back to the problem that started this.  I could very well be on the wrong track in how I am approaching my problem. The problem I had was that I wanted a generic of data_type to inherit a generic of data_type.  i.e.: Code: [Select]generic TMyListBase = class   Procedure VirtualProc( data : data_type ); virtual; abstract;   Procedure InternalProc; // <-- which uses VirtualProc end; generic TMyList = class (specialize TMyListBase)   .. whatever I need goes here .. end;  Then, I can make Code: [Select]TIntegerList = specialize TMyList TBooleanList = specialize TMyList TStringList = specialize TMyList etc.. and have them implement their own VirtualProc and I only had to define InternalProc once! Now, I *do* actually have a working workaround to this problem, but ideally I'd like it to be solved as stated above. Also, my problem is in fact not wholly mine!  I share it with another programmer:  http://forum.lazarus.freepascal.org/index.php?topic=9933.0 My solution using interjections follows, with example usage: ----START OF CODE a generic inheriting a generic in a generic way-- Code: [Select]{ In this unit we will construct the classes:   TMyListBoolean, TMyListByte, TMyListInteger   TMyListBaseBoolean, TMyListBaseByte, TMyListBaseInteger } unit TMyLists; interface uses   Classes; type Interjection GTMyListBase_interface; start   GTMyListBase = class     Procedure VirtualProc( data : data_type ); virtual; abstract;     Procedure InternalProc;   end; stop; Interjection GTMyList_interface; start   generic GTMyList = class (GTMyListBase)     Procedure VirtualProc; override;   end;  stop; Interjection Interface_Code( TypePtr : pointer ); start   {$extdef 'data_type' := NameThatType(TypePtr)}   {$extdef 'GTMyListBase' := 'TMyListBase' + NameThatType(TypePtr)}   {$extdef 'GTMyList' := 'TMyList' + NameThatType(TypePtr)}     {$Interject GTMyListBase_interface}     {$Interject GTMyList_interface}   {$unextdef 'data_type'}   {$unextdef 'GTMyListBase'}   {$unextdef 'GTMyList'}    stop; {$Interject Interface_Code( boolean )} {$Interject Interface_Code( byte )} {$Interject Interface_Code( integer )} implementation Interjection GTMyListBase_implementation( TypePtr : pointer ); start   Procedure GTMyListBase.InternalProc( data : data_type );   begin     writeln( 'InternalProc was just invoked from inside TMyListBase!' );     writeln( 'Now calling VirtualProc with data = ', data );        VirtualProc( data );    end; stop; Interjection Implementation_Code( TypePtr : pointer ); start   {$extdef 'data_type' := NameThatType(TypePtr)}   {$extdef 'GTMyListBase' := 'TMyListBase' + NameThatType(TypePtr)}     {$Interject GTMyListBase_implementation}   {$unextdef 'data_type'}   {$unextdef 'GTMyListBase'} stop; {$Interject Implementation_Code( boolean )} {$Interject Implementation_Code( byte )} {$Interject Implementation_Code( integer )} Procedure TMyListBoolean.VirtualProc( data : data_type ); begin   writeln( 'VirtualProc was just invoked from inside TMyListBoolean with data = ', data ); end; Procedure TMyListByte.VirtualProc( data : data_type ); begin   writeln( 'VirtualProc was just invoked from inside TMyListByte with data = ', data ); end; Procedure TMyListInteger.VirtualProc( data : data_type ); begin   writeln( 'VirtualProc was just invoked from inside TMyListInteger with data = ', data ); end; var    booleanlist : TMyListBoolean;    bytelist : TMyListByte;    integerlist : TMyListInteger; begin   booleanlist := TMyListBoolean.Create;   bytelist := TMyListByte.Create;   integerlist := TMyListInteger.Create;     writeln( 'Now calling TMyListBoolean''s InternalProc with data = ', true );      booleanlist.InternalProc( true );   writeln;      writeln( 'Now calling TMyListByte''s InternalProc with data = ', 250 );      bytelist.InternalProc( 250 );   writeln;     writeln( 'Now calling TMyListInteger''s InternalProc with data = ', -10 );      integerlist.InternalProc( -10 );   writeln;     FreeAndNil( booleanlist );   FreeAndNil( bytelist );   FreeAndNil( integerlist ); end. THE OUTPUT OF THE ABOVE PROGRAM IS: Now calling TMyListBoolean's InternalProc with data = TRUE InternalProc was just invoked from inside TMyListBase! Now calling VirtualProc with data = TRUE VirtualProc was just invoked from inside TMyListBoolean with data = TRUE Now calling TMyListByte's InternalProc with data = 250 InternalProc was just invoked from inside TMyListBase! Now calling VirtualProc with data = 250 VirtualProc was just invoked from inside TMyListByte with data = 250 Now calling TMyListInteger's InternalProc with data = -10 InternalProc was just invoked from inside TMyListBase! Now calling VirtualProc with data = -10 VirtualProc was just invoked from inside TMyListInteger with data = -10 ----END OF CODE a generic inheriting a generic in a generic way---- What are the advantages of interjections over templates? 1) -We can have all required code in one file 2) -Thus, it is more readable 3) -Perhaps we could make the debugger step through the interjections just like we do normal procedures and also convert the code using the macros *on* *the* *fly*!  That would be cool! 4) -Also, it would be great if the debugger was able to go to the line of code that is problematic when compiling, and show appropriate identifier names Problems encountered, disadvantages: 1) -It is not as clean as actually having a generic inherit a generic; maybe the compiler can use interjections and "hide" all of the above so the programmer does not have to bother with the nitty-gritty 2) -It should be possible to use interjections defined outside your unit if the unit is used.  In doing so, however, sometimes you may be required to share certain variables between units that you would otherwise not want to. ------ Now, can this be of any help to anyone?  I hope so!  Personally, I'd be able to use interjections to simplify my work. Now, I've probably made lots and lots of mistakes above..  so please take it all with a heaping cup of salt (plus I originally wrote most of it at night, couldn't sleep again..). And if you can tell me how to make a generic class inherit a generic class in a generic way - without interjections - then please tell me, before I write this. Hope you dream wonderful programs in the future! IndigoBoy83 ---------------------------------------------------------------------- taazz · 2015-02-20 21:21 merge them in one thread please and delete the second. ---------------------------------------------------------------------- IndigoBoy83 · 2015-02-20 22:32 Quote from: taazz on February 20, 2015, 10:21:26 pmmerge them in one thread please and delete the second. I'm sorry.  It says: "The following error or errors occurred while posting this message: The message exceeds the maximum allowed length (20000 characters)." What to do? ---------------------------------------------------------------------- taazz · 2015-02-20 22:51 reply to your first message with the rest of the second part