10

Despite years of Delphi programming I just ran into a class declaration style I had never seen for a class that supports IUnknown:

TBCUnknown = class(TBCBaseObject, IUnKnown)
private
  FRefCount: integer;
  FOwner   : Pointer;
protected
  function IUnknown.QueryInterface = NonDelegatingQueryInterface;
  function IUnknown._AddRef = NonDelegatingAddRef;
  function IUnknown._Release = NonDelegatingRelease;
  function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
...

As you can see, assignments of class methods to IUnknown interface methods are being done right in the class declaration. This looks really strange to me especially since I don't see how the IUnknown methods could be assigned to, before the constructor is called. Is this some kind of compile-time shortcut for making assignments between a class's methods and the interface pointers for an interface the class accepts, that are later resolved at run-time? If someone could provide a little information on how this works and what Delphi idiom supports this kind of construct I'd like to know.

Robert Oschler
  • 14,153
  • 18
  • 94
  • 227

2 Answers2

12

It's called Method Resolution Clause and it allows you to specify which method actually implements the specified interface method. This means that the implementing method can have a different name than the method declared in the interface (but the method signature still has to match). Without the clause, Delphi automatically resolves the implementation methods based on their names.

In your example, the declaration means that IUnknown._AddRef is implemented by TBCUnknown.NonDelegatingAddRef and IUnknown._Release by TBCUnknown.NonDelegatingRelease.

As far as I know, this has been supported from the beginning when interface support was added to the language. You probably haven't noticed it because it's not used or needed so often.

Ondrej Kelle
  • 36,941
  • 2
  • 65
  • 128
  • 1
    Certainly present in D5. I suspect like you that method resolution was available from the get go. – David Heffernan Nov 14 '11 at 16:05
  • @TOndrej. Thanks. I up-voted yours and David's comment but accepted David's answer because the system shows it as coming in 1 minute before yours did. A photo finish as they say but unfortunately Stack Overflow only allows the acceptance of one answer. – Robert Oschler Nov 14 '11 at 16:15
  • 2
    @RobertOschler Does it really? Here it shows 2 minutes after mine. – Ondrej Kelle Nov 14 '11 at 16:19
  • 2
    @Robert TOndrej answered before me. We were writing our answers at the same time. I strongly believe that you should accept the *best* answer rather than the first answer. It's entirely up to you to judge which answer is the best. – David Heffernan Nov 14 '11 at 16:29
  • David, they seemed about equivalent so I went by the time. I agree with your sentiment of course. @TOndrej. On my screen at the time I accepted it said "9 minutes ago" for David's and "10 minutes ago" for you. Now it shows "26 minutes ago" for David and "28 minutes ago" for you so David's was 2 minutes sooner and his lead is widening. I'll leave this one up to the "Einstein's relativity" physicists to figure out. :) – Robert Oschler Nov 14 '11 at 16:33
  • 1
    So, you mean 9 minutes ago happened earlier than 10 minutes ago? :-) – Ondrej Kelle Nov 14 '11 at 16:34
  • @TOndrej. Ugh, you're right. I got the temporal relationships backwards in my head. That's what I get for coding all night. Just fixed it. – Robert Oschler Nov 14 '11 at 16:36
  • 2
    :-) Thanks. Anyway, I agree with David that you should accept what you think is the best answer (I hope you did in this case). – Ondrej Kelle Nov 14 '11 at 16:37
  • 3
    @Robert I would also say that, in general, if you wait 24 hours or so before accepting an answer then you are likely to get more answers, and better, more in depth answers. In this case there's nothing much more to say than what has already been said. But for a more complex question if you leave it open a while that encourages people to add really good answers that take more time to produce. – David Heffernan Nov 14 '11 at 16:41
3

This is what is known as a Method Resolution Clause. To quote from the documentation:

You can override the default name-based mappings by including method resolution clauses in a class declaration. When a class implements two or more interfaces that have identically named methods, use method resolution clauses to resolve the naming conflicts.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490