views:

267

answers:

2

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?

+2  A: 

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;
TOndrej
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
If there's anything unsafe in the example I added above please let me know, thanks.
TOndrej
@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
@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
@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
@Craig: Agreed, thanks!
TOndrej
+8  A: 

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
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
So the short answer is while GUIDs are optional not using them limits what you can do with interfaces.
codeelegance