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
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.
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); 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
type IFoo = public interface method One; method Two; optional; end;
type ISoftDuck = public soft interface method Quack; end;
The visibility of an interface type can be controlled by applying a Visibility Modifier on the declaration. The default visibility is
One Type Modifier can be applied to classes: