Explicit Interface Implementations

When a Class or Record declares that it implements an Interface, the compiler will by default map members declared in the type to those required by the interface, using name and signature:

type
  IFoo = public Interface
    method Bar;
  end;

  Foo = public class(IFoo)
    method Bar;             // automatically maps to IFoo.Bar
  end;

Sometimes, this behavior is not desirable, and the implements Member Modifier can be used to override it by explicitly providing a mapping from members to their interface equivalent.

Explicitly Implementing Individual Members

Individual members can be mapped to an interface member that they don't match by name, by using the implements modifier, combined with the name of the interface and the name of the interface member it should be mapped to:

type
  IFoo = public Interface
    method Bar;
  end;

  Foo = public class(IFoo)
    method Bar;
    method Baz; implements IFoo.Bar; // explicitly maps to IFoo.Bar
  end;

This can be be helpful in a variety of situations, for example if

  • the type already contains a different member of the same name that is not related to the interface
  • the type implements two or more interfaces that expect a member of the same name (but require different implementations)
  • the name required by the interface does not make sense on the context of other members of the class, or could cause confusion

When an explicit mapping is provided, the member is accessible by its real name, when calling it on a reference of the type itself, and on via the interface's name when calling it on an interface reference:

var f := new Foo();
f.Bar;                // calls Foo.Bar
f.Baz;                // calls Foo.Baz
var g: IFoo := f;
g.Bar;                // calls Foo.Baz

Platform Considerations

Due to platform limitations, Explicit Interface Members are only supported on the .NET and Island platforms. On Cocoa and Java, interface members must match in name.

Delegating the Implementation of an Entire Interface

The implements modifier can also be used to delegate the implementation of an entire interface to a different type stored in a Field or Property of the type. This can be helpful to reuse an existing implementation of an interface in multiple places, or to be able to "switch out" concrete implementations of the interface at runtime (by assigning a different value to the field or property):

type
  IFoo = public Interface
    method Foo;
    method Bar;
    method Baz;
  end;

  Foo = public class(IFoo)
    method Foo;
    method Bar;
    method Baz;
  end;
  
  MyClass = public class(IFoo)
  public
    var fFoo: Object; implements IFoo;
  end;

In the above example, the Foo class provides a complete implementation of IFoo. MyClass declares the interface as well, bu does not provide its own implementation for the three methods. Instead, it delegates that implementation to the fFoo field.

var m := new MyClass();
m.Foo;                   // compiler error, Foo is not accessible here
(m as IFoo).Foo;         // calls fFoo.Foo

By default, members from a deferred interface implementation are not available on the type itself, but only through the interface. Optionally, a Visibilty Modifier can be provided to make the interface members available on the class, as well:

  MyClass = public class(IFoo)
  public
    var fFoo: Object; implements public IFoo;  // members of IFoo are publicly available on MyClass
    var fBar: Object; implements private IBar; // members of IBar are only privately available
  end;

var m := new MyClass();
m.Foo;                   // now allows call to fFoo.Foo

Platform Considerations

Due to platform limitations, Deferred Interface Implementations on the Cocoa and Java must specify visibility.

See Also