Explicit interface implementations solved for Delphi 8

published: Sat, 17-Jan-2004   |   updated: Thu, 27-Oct-2005

A few days ago I was trying to solve a particular problem with Delphi 8 that was somewhat easy in C#: implementing interfaces explicitly. (You can read about it here.)

It turns out that I was almost there, but wasn't seeing or making the final step. A reader from Russia (Arioch), whom I understand is not even a Delphi programmer (do I have egg on my face, or what? <g>), made a couple of suggestions to try and solve the problem, one of which worked beautifully.

Here's the suggestion tnat worked, which I've converted into a small test app.

program Test;

{$apptype console}

uses 
  System.Collections;

type
  Foo = class(TObject, ICloneable)
    private
    protected
      function i_Clone : TObject;
    public
      // implement ICloneable   
      function ICloneable.Clone = i_Clone;
      
      // the Clone we really want
      function Clone : Foo;
  end;

function Foo.i_Clone : TObject;
begin
  Console.WriteLine('Enter i_Clone');
  Result := Clone;
  Console.WriteLine('Leave i_Clone');
end;

function Foo.Clone : Foo;
begin
  Console.WriteLine('Enter Clone');
  Result := Foo.Create;
  Console.WriteLine('Leave Clone');
end;

var
  f : Foo;
  f2 : Foo;
  f3 : Foo;
begin
  Console.WriteLine('Create a Foo');
  f := Foo.Create;
  Console.WriteLine('Clone the Foo directly');
  f2 := f.Clone;
  Console.WriteLine('Cast the Foo to an ICloneable instance, then clone it');
  f3 := Foo(ICloneable(f).Clone);
end.

The thing to notice here is that the ICloneable.Clone method is pointing directly to a protected method with the right signature, but with a different name. My previous attempts tried to point the ICloneable.Clone method to another method called Clone, which messed me up with method overload errors. (By the way, I know that Clone isn't really cloning anything, the code is there just to make sure the test app compiles.)

The result of running the app is what we'd expect:

C:\TestApps>test
Create a Foo
Clone the Foo directly
Enter Clone
Leave Clone
Cast the Foo to an ICloneable instance, then clone it
Enter i_Clone
Enter Clone
Leave Clone
Leave i_Clone

As you can see, this solution gives me the effect I wanted: a class that implements an interface, and a way of 'hiding' the interface's non-type-safe methods in favor of type-safe versions. Thanks, Arioch!