Recent

Author Topic: Interface problem  (Read 1768 times)

mikerabat

  • Jr. Member
  • **
  • Posts: 55
Interface problem
« on: March 01, 2026, 10:09:35 pm »
I have a bit of a delicate problem...

This idea compiles in Delphi well:

Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode Delphi}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}
  7.   cthreads,
  8.   {$ENDIF}
  9.   Classes, SysUtils, CustApp
  10.   { you can add units after this };
  11.  
  12. type
  13.   IBaseIntf = interface
  14.   ['{99B2F4ED-0F79-47BD-8F77-594CD26C5FD1}']
  15.     function TestBase( a : integer ) : integer;
  16.   end;
  17.  
  18. type
  19.   IDerriveIntf = interface(IBaseIntf)
  20.   ['{C9C458E1-EB08-45ED-B7DE-EA9FBF3ADFD3}']
  21.     function TestDerrive(a : integer) : Integer;
  22.   end;
  23.  
  24. type
  25.  
  26.   { TBaseClass }
  27.  
  28.   TBaseClass = class(TInterfacedObject, IBaseIntf)
  29.   protected
  30.     function IBaseIntf.TestBase = TestBaseI;
  31.     function TestBaseI( a : integer ) : integer;
  32.   end;
  33.  
  34. type
  35.  
  36.   { TDerrivedClass }
  37.  
  38.   TDerrivedClass = class(TBaseClass, IDerriveIntf)
  39.   protected
  40.     function TestDerrive(a : integer) : Integer;
  41.   end;
  42.  
  43. type
  44.  
  45.   { TIntfTestApp }
  46.  
  47.   TIntfTestApp = class(TCustomApplication)
  48.   protected
  49.     procedure DoRun; override;
  50.   public
  51.   end;
  52.  
  53. { TBaseClass }
  54.  
  55. function TBaseClass.TestBaseI(a: integer): integer;
  56. begin
  57.      Result := a - 4;
  58. end;
  59.  
  60. { TDerrivedClass }
  61.  
  62. function TDerrivedClass.TestDerrive(a: integer): Integer;
  63. begin
  64.      Result := a + 4;
  65. end;
  66.  
  67. { TIntfTestApp }
  68.  
  69. procedure TIntfTestApp.DoRun;
  70. var
  71.   ErrorMsg: String;
  72.   a : IDerriveIntf;
  73.   b : IBaseIntf;
  74. begin
  75.    a := TDerrivedClass.Create;
  76.    Writeln(a.TestDerrive(44));
  77.    Writeln(a.TestBase(44));
  78.    b := TBaseClass.Create;
  79.    Writeln(b.TestBase(44));
  80.  
  81.    readln;
  82.  
  83.   // stop program loop
  84.   Terminate;
  85. end;
  86.  
  87. var
  88.   Application: TIntfTestApp;
  89. begin
  90.   Application:=TIntfTestApp.Create(nil);
  91.   Application.Title:='Interface Test';
  92.   Application.Run;
  93.   Application.Free;
  94. end.
  95.  

And by idea I mean that there is a base interface def, a derrived one that includes the base interface and two classes that implement these interfaces.
Note that I need some kind of delegation in the base class in the form
IBaseIntf.TestBase = TestBaseI

In this case - if I have a delegating declaration like this the compiler starts to mock and throws an "this is not implemented" error. My problem is that this compiles in Delphi :/ . Is there anything that I can do in that regard? How can I fix the compile error - without removing the "delegation" stuff.

Background is that:
* I want to have a generic base matrix interface and class
* 2 derrived classes for complex and real valued matrices
* 2 derrived interfaces that implement complex and double valued matrices with the overlap of generic (IMatrix) functions that sometimes are also are superseeded (with the same name) in the derrived classes.

Note that the delphi implementation on github.com/mikerabat/mrmath already does all these things but I'm stuck now with the FPC stuff :/

Is there anything I can do in that regard?

kind regards
  Mike

LeP

  • Full Member
  • ***
  • Posts: 198
Re: Interface problem
« Reply #1 on: March 02, 2026, 12:39:01 am »
By now, I think you have to insert a duplicate declaration of TestBase:

Code: Pascal  [Select][+][-]
  1. type
  2.  
  3.   { TDerrivedClass }
  4.  
  5.   TDerrivedClass = class(TBaseClass, IDerriveIntf)
  6.   protected
  7.     function IDerriveIntf.TestBase = TestBaseI; <--------------------
  8.     function TestDerrive(a : integer) : Integer;
  9.   end;

I don't know if that works but I think FPC wants that.

jamie

  • Hero Member
  • *****
  • Posts: 7589
Re: Interface problem
« Reply #2 on: March 02, 2026, 12:24:04 pm »
I tried his code in an older version of delphi and good basically the same error.

Maybe newer versions work this out.
The only true wisdom is knowing you know nothing

LeP

  • Full Member
  • ***
  • Posts: 198
Re: Interface problem
« Reply #3 on: March 02, 2026, 02:52:33 pm »
I install Lazarus now (4.6) and I try the original code and doesn't works, but it works in the last Delphi release.

Adding what I write in my post make the code working in Lazarus.

The original code can be used only in case expresses by OP, cause if you have (for example) the overload methods in the interface you cannot inherited the functions through a delegation.

mikerabat

  • Jr. Member
  • **
  • Posts: 55
Re: Interface problem
« Reply #4 on: March 02, 2026, 03:37:21 pm »
I used the delegation method especially because there are overloaded functions so I do not have introduce casts as much. They should be automatically handled by the compiler
(and in theory there is no ambiguity). But it seems I cannot do this this here...

LeP

  • Full Member
  • ***
  • Posts: 198
Re: Interface problem
« Reply #5 on: March 02, 2026, 04:25:41 pm »
I used the delegation method especially because there are overloaded functions so I do not have introduce casts as much. They should be automatically handled by the compiler
(and in theory there is no ambiguity). But it seems I cannot do this this here...
At that time I think that for what you needs the interface methods should supports generics or some some other compiler "magic".
But as a famous movie said, this is not the time.

Without delegation, there were no problems.

May be some other people can answer with more knowledge.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6349
  • Compiler Developer
Re: Interface problem
« Reply #6 on: March 02, 2026, 10:15:54 pm »
Is there anything I can do in that regard?

As LeP said, you need to declare the method alias for IDerriveIntf as well.

Other than that, please report a bug with your example considering that it works in Delphi.

Thaddy

  • Hero Member
  • *****
  • Posts: 18764
  • To Europe: simply sell USA bonds: dollar collapses
Re: Interface problem
« Reply #7 on: March 03, 2026, 10:17:31 am »
The original statement that it - the presented code - compiles in Delphi is incorrect. Frankly: false.
The code needs quite some changes to make it compile since Delphi does not know custapp.
(Tested D7 and D12 CE)

And when you eliminate the custapp use, it still only works with LeP 's modification.

And that is to be expected, since the first alias is an implementation alias and the second one is not automatically assigned from the use of the interface alone, so it also needs an implementation alias.

So LeP's code is the correct solution for BOTH Delphi and FPC.
« Last Edit: March 03, 2026, 10:26:00 am by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

LeP

  • Full Member
  • ***
  • Posts: 198
Re: Interface problem
« Reply #8 on: March 03, 2026, 10:47:12 am »
The original statement that it - the presented code - compiles in Delphi is incorrect. Frankly: false.
The code needs quite some changes to make it compile since Delphi does not know custapp.
(Tested D7 and D12 CE)

And when you eliminate the custapp use, it still only works with LeP 's modification.

And that is to be expected, since the first alias is an implementation alias and the second one is not automatically assigned from the use of the interface alone, so it also needs an implementation alias.

So LeP's code is the correct solution for BOTH Delphi and FPC.
No, this is not right. Custom APP has nothing to do with the ISSUE. You can delete all custom app related and still have the ISSUE in Lazarus (FPC).
The original code works with Delphi (Custom App excluded of course), but also with "{$mode Delphi}{$H+}" excluded of course , and .... of course .....

Thaddy

  • Hero Member
  • *****
  • Posts: 18764
  • To Europe: simply sell USA bonds: dollar collapses
Re: Interface problem
« Reply #9 on: March 03, 2026, 11:00:11 am »
I know that custapp has nothing to do with the issue, but it has to do with the original claim.
I tested that, removed custapp code, and it did NOT work in D7 or D12.CE without your modification.
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

LeP

  • Full Member
  • ***
  • Posts: 198
Re: Interface problem
« Reply #10 on: March 03, 2026, 11:06:31 am »
I know that custapp has nothing to do with the issue, but it has to do with the original claim.
I tested that, removed custapp code, and it did NOT work in D7 or D12.CE without your modification.
Read better: LAST DELPHI RELEASE. I mean the official Delphi 13 Florence.

If you refer to old product (CE it's based as tech on April 2024, and released on August 2024) may be you are right.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12706
  • FPC developer.
Re: Interface problem
« Reply #11 on: March 03, 2026, 11:38:15 am »
I know that custapp has nothing to do with the issue, but it has to do with the original claim.
I tested that, removed custapp code, and it did NOT work in D7 or D12.CE without your modification.
Read better: LAST DELPHI RELEASE. I mean the official Delphi 13 Florence.

If you refer to old product (CE it's based as tech on April 2024, and released on August 2024) may be you are right.

I also removed the customapp ancestor, change run to dorun, and change create(NIL) to create() and it works in Seattle (Delphi 10.0), printing 48,40,40

The question if that is accident or not, is the question. Probably we would need tests that dump the interface tables.

I haven't used interfaces much in recent times, but I can remember from the old days that it was a kind of rule in FAQs and forums to always declare all interfaces in the final (to use) class. However that might be meant for cases where only IderriveIntf is declared, and where the ancestor interface must be explicitly named. It might not apply here since IBaseIntf is declared in an ancestor class.

« Last Edit: March 03, 2026, 12:00:41 pm by marcov »

mikerabat

  • Jr. Member
  • **
  • Posts: 55
Re: Interface problem
« Reply #12 on: March 03, 2026, 11:54:48 am »
I know that custapp has nothing to do with the issue, but it has to do with the original claim.
I tested that, removed custapp code, and it did NOT work in D7 or D12.CE without your modification.

Actually this is not true at all. I tested this code with D2010 and D13 - and frankly I do not expect a problem with D12:
here the adjusted - delphi compilable program.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8.   Classes,
  9.   SysUtils;
  10.  
  11. type
  12.   IBaseIntf = interface
  13.   ['{99B2F4ED-0F79-47BD-8F77-594CD26C5FD1}']
  14.     function TestBase( a : integer ) : integer;
  15.   end;
  16.  
  17. type
  18.   IDerriveIntf = interface(IBaseIntf)
  19.   ['{C9C458E1-EB08-45ED-B7DE-EA9FBF3ADFD3}']
  20.     function TestDerrive(a : integer) : Integer;
  21.   end;
  22.  
  23. type
  24.  
  25.   { TBaseClass }
  26.  
  27.   TBaseClass = class(TInterfacedObject, IBaseIntf)
  28.   protected
  29.     function IBaseIntf.TestBase = TestBaseI;
  30.     function TestBaseI( a : integer ) : integer;
  31.   end;
  32.  
  33. type
  34.  
  35.   { TDerrivedClass }
  36.  
  37.   TDerrivedClass = class(TBaseClass, IDerriveIntf)
  38.   protected
  39.     function TestDerrive(a : integer) : Integer;
  40.   end;
  41.  
  42. { TBaseClass }
  43.  
  44. function TBaseClass.TestBaseI(a: integer): integer;
  45. begin
  46.      Result := a - 4;
  47. end;
  48.  
  49. { TDerrivedClass }
  50.  
  51. function TDerrivedClass.TestDerrive(a: integer): Integer;
  52. begin
  53.      Result := a + 4;
  54. end;
  55.  
  56. { TIntfTestApp }
  57.  
  58. procedure DoRun;
  59. var
  60.   a : IDerriveIntf;
  61.   b : IBaseIntf;
  62. begin
  63.    a := TDerrivedClass.Create;
  64.    Writeln(a.TestDerrive(44));
  65.    Writeln(a.TestBase(44));
  66.    b := TBaseClass.Create;
  67.    Writeln(b.TestBase(44));
  68.  
  69.    readln;
  70.  
  71. end;
  72.  
  73. begin
  74.   DoRun;
  75. end.
  76.  

PascalDragon

  • Hero Member
  • *****
  • Posts: 6349
  • Compiler Developer
Re: Interface problem
« Reply #13 on: March 05, 2026, 09:22:57 pm »
And when you eliminate the custapp use, it still only works with LeP 's modification.

I had tested with Delphi 10.2 and after adjusting for CustApp related issues it compiled.

 

TinyPortal © 2005-2018