Am 18.02.2021 um 23:58 schrieb Ryan Joseph via fpc-pascal:

On Feb 18, 2021, at 3:07 PM, Sven Barth <pascaldra...@googlemail.com> wrote:

So "class type method resolution" is what's missing? I never used the interface 
method resolution so I don't really understand this feature. What needs to happen as far 
as the compiler is concerned?
The problem is this: if you have a property with an interface type the compiler 
can simply build the interface's VMT for this. However for classes (or objects 
or records) the compiler needs to generate slightly different thunks that fixup 
the correct Self value, especially if things are mixed between the subclass and 
the container class.
Then this is the real challenge to implement a "default implements property" 
and something I know nothing about. :) The rest is pretty easy actually though.

Correct, that is the real challenge ;)


type
   TMyShape = class(TShape, ICircle)
     private
       m_circle: TCircle;
     protected
       procedure ICircle.Draw = Draw;
     public
       property circle: TCircle read m_circle implements ICircle;
   end;
Your specific example is rather useless, cause your interface only has a single 
method that you redirect to the class' method thus you wouldn't need to use 
interface delegation. But anyway, your code would generate a runtime error, 
because your TMyShape.Draw would still be abstract.
Maybe it's a bad example but I'm trying to illustrate how method resolution 
could be used for overriding (or what ever it would be called in this context.

I know this isn't correct syntax but it's more of this direction:

procedure Draw =  ICircle.Draw;

TShape.Draw is resolved by ICircle.Draw, which is implemented via TCircle. It's 
quasi-overriding but the VMT table should point to m_circle.Draw so Draw could be called 
on TShape and get property resolved by the "implements ICircle" property. Hope 
that makes sense.
Let me get it straight: your example is that both TShape and TCircle provide a Draw method, but in TMyShape you want TCircle.Draw to be used instead of TShape.Draw when TMyShape.Draw is called. Correct so far?

Well that would work without any additional declarations. The idea would be that the "default" modifier would lead to conflicts only if a Draw method exists in TMyShape itself. If it's declared in one of the parents then that won't matter.

The only thing that will not work and which will continue not to work is that m_circle.Draw will not be called if you access the TMyShape through a TShape.Draw call. For that one needs to use an explicit declaration:

=== code begin ===

type
  TMyShape = class(TShape, ICircle)
  private
    m_circle: TCircle;
  public
    procedure ICircle.Draw = Draw;
    property Circle: TCircle read m_circle implements ICircle;
    procedure Draw; override;
  end;

procedure TMyShape.Draw;
begin
  m_circle.Draw;
end;

=== code end ===

This way it does not matter if TCircle is a class, a record or an object, cause it will always work correctly.

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to