Schnittstellen (F#)
Schnittstellen geben Sätze von verwandten Membern an, die von anderen Klassen implementiert werden.
// Interface declaration:
[ attributes ]
type interface-name =
[ interface ]
[ inherit base-interface-name ...]
abstract member1 : [ argument-types1 -> ] return-type1
abstract member2 : [ argument-types2 -> ] return-type2
...
[ end ]
// Implementing, inside a class type definition:
interface interface-name with
member self-identifier.member1 argument-list = method-body1
member self-identifier.member2 argument-list = method-body2
// Implementing, by using an object expression:
[ attributes ]
let class-name (argument-list) =
{ new interface-name with
member self-identifier.member1 argument-list = method-body1
member self-identifier.member2 argument-list = method-body2
[ base-interface-definitions ]
}
member-list
Hinweise
Schnittstellendeklarationen ähneln Klassendeklarationen, mit dem Unterschied, dass keine Member implementiert werden.Stattdessen sind alle Member abstrakt, wie durch das Schlüsselwort abstract angegeben.Für abstrakte Methoden wird kein Methodentext bereitgestellt.Sie können jedoch eine Standardimplementierung bereitstellen, indem Sie außerdem eine eigene Definition des Members als Methode zusammen mit dem default-Schlüsselwort einschließen.Dies entspricht dem Erstellen einer virtuellen Methode in einer Basisklasse in anderen .NET-Sprachen.Eine solche virtuelle Methode kann in Klassen überschrieben werden, die die Schnittstelle implementieren.
Es gibt zwei Möglichkeiten, Schnittstellen zu implementieren: mit Objektausdrücken und mit Klassentypen.In beiden Fällen stellt der Klassentyp bzw. Objektausdruck den Methodentext für abstrakte Methoden der Schnittstelle bereit.Implementierungen sind für den jeweiligen Typ spezifisch, der die Schnittstelle implementiert.Daher können sich Schnittstellenmethoden für verschiedene Typen voneinander unterscheiden.
Die Schlüsselwörter interface und end, die den Anfang und das Ende der Definition markieren, sind optional, wenn Sie einfache Syntax verwenden.Wenn Sie diese Schlüsselwörter nicht verwenden, versucht der Compiler per Rückschluss abzuleiten, ob der Typ eine Klasse oder eine Schnittstelle ist, indem er die verwendeten Konstrukte analysiert.Wenn Sie einen Member definieren oder andere Klassensyntax verwenden, wird der Typ als Klasse interpretiert.
Im .NET-Codierungsstil beginnen alle Schnittstellen mit dem Großbuchstaben I.
Implementieren von Schnittstellen mit Klassentypen
Sie können eine oder mehrere Schnittstellen in einem Klassentyp implementieren, indem Sie das interface-Schlüsselwort, den Namen der Schnittstelle und das with-Schlüsselwort, gefolgt von den Schnittstellenmemberdefinitionen verwenden, wie im folgenden Code gezeigt.
type IPrintable =
abstract member Print : unit -> unit
type SomeClass1(x: int, y: float) =
interface IPrintable with
member this.Print() = printfn "%d %f" x y
Schnittstellenimplementierungen werden geerbt. Abgeleitete Klassen müssen sie also nicht erneut implementieren.
Aufrufen von Schnittstellenmethoden
Schnittstellenmethoden können nur über die Schnittstelle, nicht über ein Objekt des Typs, der die Schnittstelle implementiert, aufgerufen werden.Daher müssen Sie möglicherweise mit dem Operator :> oder upcast eine Aufwärtsumwandlung in den Schnittstellentyp ausführen, um diese Methoden aufzurufen.
Wenn Sie über ein Objekt des Typs SomeClass verfügen, müssen Sie zum Aufrufen der Schnittstellenmethode den Typ des Objekts per Aufwärtsumwandlung in den Schnittstellentyp umwandeln, wie im folgenden Code gezeigt.
let x1 = new SomeClass1(1, 2.0)
(x1 :> IPrintable).Print()
Als Alternative kann eine Methode für das Objekt deklariert werden, die die Aufwärtsumwandlung ausführt und die Schnittstellenmethode aufruft, wie im folgenden Beispiel gezeigt.
type SomeClass2(x: int, y: float) =
member this.Print() = (this :> IPrintable).Print()
interface IPrintable with
member this.Print() = printfn "%d %f" x y
let x2 = new SomeClass2(1, 2.0)
x2.Print()
Implementieren von Schnittstellen mit Objektausdrücken
Objektausdrücke bieten ein schnelles Verfahren zum Implementieren einer Schnittstelle.Sie sind hilfreich, wenn Sie keinen benannten Typ erstellen müssen und nur ein Objekt benötigen, das die Schnittstellenmethoden unterstützt, ohne zusätzliche Methoden.Ein Objektausdruck wird im folgenden Code veranschaulicht.
let makePrintable(x: int, y: float) =
{ new IPrintable with
member this.Print() = printfn "%d %f" x y }
let x3 = makePrintable(1, 2.0)
x3.Print()
Schnittstellenvererbung
Eine Schnittstelle kann von einer oder mehreren Basisschnittstellen erben.
type Interface1 =
abstract member Method1 : int -> int
type Interface2 =
abstract member Method2 : int -> int
type Interface3 =
inherit Interface1
inherit Interface2
abstract member Method3 : int -> int
type MyClass() =
interface Interface3 with
member this.Method1(n) = 2 * n
member this.Method2(n) = n + 100
member this.Method3(n) = n / 10