On 02/02/2026 20:48, Michael Van Canneyt via fpc-devel wrote:

Are you deliberately trying to shoot yourself in the foot here ?
(better your foot than my foot obviously...)

Well, the simplest would be

   generic TGen<DATA>

no constraint, I can pass in whatever, and if it has the methods, then good ... (or well...)

But, that feels more like risking my foot. I quite prefer if I can give a constraint, and if the compiler will know earlier what the generic is about.

I have a list. Well several lists. They share some functionality.
But I can't just pack it into a base class.

For once, at least in some parts of the code, the list will only be known as "interface".

The lists have different item classes too.  So now I thought I write a generic that implements the shared bit. Actually the shared bit is in another class, that accepts the list as argument. A worker class, if you will.

generic SharedBit<_BASE, _LIST, _ITEM> = class(_BASE)
  procedure ProcessItem(Itm: _ITEM);  virtual; // called by DoFoo
  procedure DoFoo(List: _LIST);
end;

procedure DoFoo(List: _LIST);
begin
  ProcessItem(List.Entries[i]);  // Entries must return the specific interface
end

ProcessItem must have the subclass, or at least the more specific interface.

And yes, I could add to the interface
  function GetObject: TObject
and then type cast that.
That feels like a bandaid.

Since I do have some code that has the list as interface, the simplest is that all code that does SharedBit uses the interfaces. (Well, yes, leave away the constraint, and I can specialize for either class or interface)






I assume this should be:

property Bar: TBar read GetBar;
yes


 property Bar: TSubBar read GetSubBar;

property overrides exist, but they must keep the same type, they can only
change the specifiers. So I don't think this will compile. If it does, it
is probably by accident.

It does actually compile.

And on classes, properties can be reintroduces with any changes possible (wouldn't necessarily do but works)

On interfaces, it does not conflict with getting the interface by it GUID, or with what the interface "contains" => i.e. its definition, as it would be seen by any other code, e.g. a 3rd party lib.
The "property" doesn't change the VMT of the interface.

It really just defines an alias within the type name of the interface (almost like a type helper).

The inherited interface, now introduces a new method, with a new name, and a new type. Completely independent method. The parent VMT has nothing hidden, all fine so far.

The property just changes the alias, which function to call. And its not bound to the vmt, it hangs on the type name of the interface (at least my understanding).



I don't know, but to me it looks like a definite way to confuse yourself and others.
Not to much confusion. It returns the same entry, but with a different type.

Well, ok. its a different interface, but the object behind it is the same object. same instance. And the returned interface inherits from the original interface too (even though that isn't enforced by the compiler)

So functional it does the same thing. It just offers additional methods.

And those added methods are what I really need to access in the overridden "ProcessItem".



I would define this as

  ISubFoo = interface(Foo)
    procedure GetSubBar: TSubBar;
    property SubBar: TSubBar;
  end;

Except, I must have it as
      property Bar: TSubBar;

=> because the code in the above generic will access "Bar".

I can pass the type for it (for the param in the virtual ProcessItem) to the generic.

But I can not pass the name of the property to the generic. The generic will always call "Bar"


_______________________________________________
fpc-devel maillist  -  [email protected]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply via email to