21

The official documentation says they are optional. I know COM interop requires a unique identifier for each interface but every interface example I see has a GUID whether it's used with COM or not? Is there any benefit to including a GUID if its not going to be used with COM?

Kenneth Cochran
  • 11,954
  • 3
  • 52
  • 117

2 Answers2

21

I've noticed that some methods such as Supports (to determine if a class conforms to a specific interface) require that you define a GUID before you can use them.

This page confirms it with the following information:

Note: The SysUtils unit provides an overloaded function called Supports that returns true or false when class types and instances support a particular interface represented by a GUID. The Supports function is used in the manner of the Delphi is and as operators. The significant difference is that the Supports function can take as the right operand either a GUID or an interface type associated with a GUID, whereas is and as take the name of a type. For more information about is and as, see Class References.

Here's some interesting information about interfaces, which states:

Why does an interface need to be uniquely identifiable? The answer is simple: because Delphi classes can implement multiple interfaces. When an application is running, there has to be a mechanism that will get pointer to an appropriate interface from an implementation. The only way to find out if an object implements an interface and to get a pointer to implementation of that interface is through GUIDs.

Emphasis added in both quotes.

Reading this entire article also makes you realize that QueryInterface (which requires a GUID) is used behind the scenes for reasons such as reference counting.

Senseful
  • 86,719
  • 67
  • 308
  • 465
  • 1
    Also, it's worth noting that attempting to use an `is` or `as` cast with an interface involves one of these calls (I forget which) under the hood, so you'll need a GUID to do that too. – Mason Wheeler Jun 07 '10 at 18:58
  • 4
    So the short answer is while GUIDs are optional not using them limits what you can do with interfaces. – Kenneth Cochran Jun 07 '10 at 20:00
  • The need to use the `Supports` function is so far the only reason I define GUID's for the interfaces. – Edwin Yip Apr 16 '12 at 09:51
  • 2
    "The only way to find out if an object implements an interface and to get a pointer to implementation of that interface is through GUIDs." Why not just query the methods of the object and check to ensure that methods with those names are present in the object? Good old duck typing? You don't see this GUID nonsense in other languages. – alcalde Jun 08 '14 at 05:37
8

Only if you need your interface to be compatible with COM.

Unfortunately, that also includes using is, as operators and QueryInterface, Supports functions - the lack of which is rather limiting. So, while not strictly required, it's probably easier to use a GUID. Otherwise, you are left with rather simplistic usage only:

type
  ITest = interface
    procedure Test;
  end;

  ITest2 = interface(ITest)
    procedure Test2;
  end;

  TTest = class(TInterfacedObject, ITest, ITest2)
  public
    procedure Test;
    procedure Test2;
  end;

procedure TTest.Test;
begin
  Writeln('Test');
end;

procedure TTest.Test2;
begin
  Writeln('Test2');
end;

procedure DoTest(const Test: ITest);
begin
  Test.Test;
end;

procedure DoTest2(const Test: ITest2);
begin
  Test.Test;
  Test.Test2;
end;

procedure Main;
var
  Test: ITest;
  Test2: ITest2;
begin
  Test := TTest.Create;
  DoTest(Test);
  Test := nil;

  Test2 := TTest.Create;
  DoTest(Test2);
  DoTest2(Test2);
end;
Ondrej Kelle
  • 36,941
  • 2
  • 65
  • 128
  • That's not right; see @eagle's answer. The only way you can use a non-COM interface without a GUID is an unsafe, hard cast. – Craig Stuntz Jun 07 '10 at 19:12
  • 1
    If there's anything unsafe in the example I added above please let me know, thanks. – Ondrej Kelle Jun 07 '10 at 19:35
  • @Craig: I'm not sure that "unsafe, hard casts" even exist for interfaces, since the compiler still needs some way to locate the Interface Table for the interface being used. – Mason Wheeler Jun 07 '10 at 20:20
  • @Mason, they do. That used to be the only way to use IProviderSupport. The VCL source code did this, at least in the D6 era. – Craig Stuntz Jun 07 '10 at 20:44
  • 1
    @TOndrej, your code is safe because you never change to an unrelated interface (multiple inheritance, effectively), which is a large part of the reason you use interfaces. Imagine an `IFoo` without a subtype relationship to `ITest`. How do you convert a reference of `ITest` to a reference of `IFoo` , presuming the implementing type supports both. You need the GUID to do it safely. – Craig Stuntz Jun 07 '10 at 20:48