David Schwartz
David Schwartz

Reputation: 1844

How to support class methods in interface definitions in Delphi

I created a class method in a class that implements an interface, but I can't seem to define it inside of the interface.

IMyClass = interface
  procedure someproc();
  class function myfunc() : TMyClass;  // compiler doesn't like this!
end;

TMyClass = class( TInterfacedObject, IMyClass )
public
  procedure someproc();
  class function myfunc() : TMyClass;
end;

I want myfunc() to create and return an instance of TMyClass. For example:

somefunc( TMyClass.myfunc(), ... );

creates an instance of TMyClass and passes it into somefunc.

I can define function myfunc() : TMyClass; in the IMyClass interface, but if I put class in front of it, the compiler gives me an error. If I leave it off, it gives me several other errors "E2291 Missing implementation of interface method xyz.myfunc" It just doesn't accept the same signature in the interface as in the class.

I thought I've seen this work before (class methods defined in interfaces) but maybe not.

If this isn't supported directly, how do you do it?

(I'm using Delphi XE5, in case it matters.)

Upvotes: 14

Views: 6713

Answers (3)

kludg
kludg

Reputation: 27493

What you are trying to achieve is impossible because it violates binary specifications of Delphi interfaces.

Any interface method in Delphi have hidden first parameter - pointer to an instance. Instance methods have the same hidden parameter (Self, the same pointer to an instance) and because of this they are binary compatible with interface methods.

On the other hand the hidden parameter of a class method is a pointer to the class vtable, so Delphi class methods are binary incompartible with Delphi interface methods.

Hypothetically you could think of the following (binary compatible) declarations:

IMyClass = interface
  procedure someproc();
  function myfunc(): TMyClass;
end;

TMyClass = class( TInterfacedObject, IMyClass )
public
  procedure someproc();
  class function myfunc(Inst: TMyClass) : TMyClass; static;
end;

Here I use static specifier to remove the hidden parameter (class vtable pointer) we don't need and add the instance pointer parameter explicitely; but the compiler does support such syntax because the above is essentially the same as a simpler

IMyClass = interface
  procedure someproc();
  function myfunc(): TMyClass;
end;

TMyClass = class( TInterfacedObject, IMyClass )
public
  procedure someproc();
  function myfunc() : TMyClass;
end;

Upvotes: 4

TridenT
TridenT

Reputation: 4909

You can define a class method (class procedure in Delphi) in a class definition (TMyClass) but not in an interface (IMyClass ).

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 598134

Interfaces are not classes and do not support methods marked as class, they only support non-class methods that are implemented and called on object instances.

What you are looking for will most likely have to be implemented as a class factory instead of using an interface.

Upvotes: 9

Related Questions