Table of Contents

Interfaces

interface declarations describe a contract that other types may implement. Interfaces are reference types; they emit as abstract CLR interfaces and cannot be instantiated directly.

interface ILogger {
    func Log(message: string) -> ()
}

Interfaces may be declared at the top level, inside namespaces, or nested inside other types. Like classes, they support the same set of member declarations (methods, properties, indexers, and nested types). Instance members are abstract requirements by default, but supplying a body for a method or accessor turns it into a default implementation emitted directly on the interface.

Static members, by contrast, must provide a body and emit as real static members on the interface type; implementing types never participate in their implementation or override process. When an interface member uses accessors, a bare ; accessor denotes an unimplemented accessor requirement (get;/set;).

Base interfaces

An interface may inherit from other interfaces by listing them after a colon. Every base must be an interface.

interface IAsyncLogger : ILogger, IDisposable {}

Implementing interfaces

Classes, structs, and union carriers implement interfaces by listing them in their base list. The optional class base (if any) must appear first, followed by one or more interfaces. Structs and unions accept interfaces only. Implementing types must provide members whose signatures match every required interface member—name, parameter count, parameter types (including by-reference modifiers), and return type must align.

class FileLogger : ILogger, IDisposable {
    func Dispose() -> () { /* release resources */ }

    func Log(message: string) -> () {
        Console.WriteLine(message)
    }
}

For a union, the interface is implemented by the carrier rather than by each generated case type:

union LogFailure: ILogger {
    case Unavailable

    func Log(message: string) -> () {
        Console.WriteLine(message)
    }
}

An explicit interface implementation qualifies the member name with the interface type: ILogger.Log. Explicit members are always instance members, ignore virtual and override, and are accessible only through the interface.

The qualifier must name an interface (RAV0313), the containing type must list that interface (RAV0314), and the interface must contain a member with the same name and signature (RAV0315).

class QuietLogger : ILogger {
    func ILogger.Log(message: string) {
        Console.WriteLine("[quiet] " + message)
    }
}
let logger = QuietLogger()
logger.Log("hi")              // error: member not found
(logger :> ILogger).Log("hi") // ok