Interfaces

Interfaces provide an abstract definition of one or more type members (Methods, Properties or Events) that other types may opt to implement. You can think of them as type contract that a type promises to provide functionality for.

Many types can implement the same interface, regardless of whether they share a common ancestry in their inheritance hierarchy, and all types implementing the interface can then be interacted with by the same code, without the code having to be aware of the actual concrete types.

Any type opting to implement an interface must provide an implementation for all members of the interface (except for those declared optional, a feature available only on Cocoa objects). All interface members are implied to be public, and no visibility sections are allowed (with the exception of Private Interface Members, discussed below).

By convention, and to provide distinction from concrete types, interface names start with an uppercase I followed by a PascalCased name. But this is not a rule that is compiler-enforced. On Java, system-provided interfaces do not follow this convention.

An interface type is declared using the interface keyword, followed by zero or more member declarations, and closed off with the end keyword. Optionally, one or more base interfaces can be provided in parenthesis behind the interface keyword:

type
  IMyInterface = public interface
    method DoSomething;
  end;

  MyClass = public class(IMyInterface)
  public
    method DoSomething; ///
  end;
  
  var x: IMyInterface;
  x.DoSomething(; // we don't know the actual type of x, only that it implements IMyInterface

Interfaces Members are limited to

Like all custom types, interfaces can be nested in other types with nested in syntax.

Default Implementations

Interfaces can optionally choose to provide a default implementation for some of the methods they define. If a default implementation is provided, types implementing the interface may choose not to provide an implementation themselves, and will in that case "inherit" the default implementation.

This is often helpful for interface methods that would be similar for most implementations. Consider the ILogger interface example below. Most concrete implementations would only need to implement the first method to emit the log string to various mediums. The second method is handy to have for callers of the interface, but it would be cumbersome having to re-implement it for each logger.

type
  ILogger = public soft interface
    method Log(aInfo: String);
    method Log(aFormat: String; params aParameters: array of Object);
    begin
      Log(String.Format(aFormat, aParameters));
    end;
  end;

Private Interface Members

As part of default implementations, interfaces can also define private helper members. These members must provide an implementation; they do not become part of the official interface contract, and are only available from other methods implemented in the same interface. Consider:

type
  ILogger = public soft interface
  public
   
    method Log(aInfo: String);
    
    method Log(aFormat: String; params aParameters: array of Object);
    begin
      Log(CustomFormat(aFormat, aParameters));
    end;
    
  private
  
    method CustomFormat(aFormat: String; params aParameters: array of Object): String;
    begin
      ...
    end;

  end;

Optional Members (Cocoa)

On the Cocoa platform, interface members can be marked as optional with the optional keyword directive. Optional members do not have to (but may) be implemented by classes conforming to the interface. Of course, code calling into such optional members must take care to ensure they are implemented by the concrete instance, at runtime – usually by calling the respondsToSelector() method on Cocoa's base Object.

type
  IFoo = public interface
    method One;
    method Two; optional;
  end;

Soft Interfaces

Interfaces can be marked as soft and suitable for automatic Duck Typing, using the soft modifier keyword. You can read more about Soft Interfaces, in all Elements languages, here.

type
  ISoftDuck = public soft interface
    method Quack;
  end;

Combined Interfaces

A Type Alias can combine two or more interfaces into a new interface type that combines both:

type
  ICodable = IEncodable and IDecodable;

See the Combined Interfaces topic for more details

Type Visibility

The visibility of an interface type can be controlled by applying a Visibility Modifier on the declaration. The default visibility is assembly.

Other Modifiers

Only one Type Modifier can be applied to interfaces:

  • soft marks the interface as soft (see above)

See Also