Interfaces specify sets of related members that other classes implement.
Syntax
F#
// Interface declaration:
[ attributes ]
type [accessibility-modifier] interface-name=
[ interface ] [ inheritbase-interface-name ...]
abstract member1 : [ argument-types1 -> ] return-type1
abstract member2 : [ argument-types2 -> ] return-type2
...
[ end ]
// Implementing, inside a class type definition:interfaceinterface-name withmember self-identifier.member1argument-list = method-body1
member self-identifier.member2argument-list = method-body2
// Implementing, by using an object expression:
[ attributes ]
letclass-name (argument-list) =
{ newinterface-name withmember self-identifier.member1argument-list = method-body1
member self-identifier.member2argument-list = method-body2
[ base-interface-definitions ]
}
member-list
Remarks
Interface declarations resemble class declarations except that no members are implemented. Instead, all the members are abstract, as indicated by the keyword abstract. You do not provide a method body for abstract methods. F# cannot define a default method implementation on an interface, but it is compatible with default implementations defined by C#. Default implementations using the default keyword are only supported when inheriting from a non-interface base class.
The default accessibility for interfaces is public.
You can optionally give each method parameter a name using normal F# syntax:
F#
typeISprintable=
abstractmember Print: format: string -> unit
In the above ISprintable example, the Print method has a single parameter of the type string with the name format.
There are two ways to implement interfaces: by using object expressions, and by using types. In either case, the type or object expression provides method bodies for abstract methods of the interface. Implementations are specific to each type that implements the interface. Therefore, interface methods on different types might be different from each other.
The keywords interface and end, which mark the start and end of the definition, are optional when you use lightweight syntax. If you do not use these keywords, the compiler attempts to infer whether the type is a class or an interface by analyzing the constructs that you use. If you define a member or use other class syntax, the type is interpreted as a class.
The .NET coding style is to begin all interfaces with a capital I.
You can specify multiple parameters in two ways: F#-style and .NET-style. Both will compile the same way for .NET consumers, but F#-style will force F# callers to use F#-style parameter application and .NET-style will force F# callers to use tupled argument application.
F#
typeINumericFSharp=
abstract Add: x: int -> y: int -> int
typeINumericDotNet=
abstract Add: x: int * y: int -> int
Implementing Interfaces by Using Class Types
You can implement one or more interfaces in a class type by using the interface keyword, the name of the interface, and the with keyword, followed by the interface member definitions, as shown in the following code.
F#
typeIPrintable=
abstractmember Print: unit -> unit
typeSomeClass1(x: int, y: float) =
interface IPrintable withmember this.Print() = printfn "%d %f" x y
Interface implementations are inherited, so any derived classes do not need to reimplement them.
Calling Interface Methods
Interface methods can be called only through the interface, not through any object of the type that implements the interface. Thus, you might have to upcast to the interface type by using the :> operator or the upcast operator in order to call these methods.
To call the interface method when you have an object of type SomeClass, you must upcast the object to the interface type, as shown in the following code.
F#
let x1 = new SomeClass1(1, 2.0)
(x1 :> IPrintable).Print()
An alternative is to declare a method on the object that upcasts and calls the interface method, as in the following example.
F#
typeSomeClass2(x: int, y: float) =
member this.Print() = (this :> IPrintable).Print()
interface IPrintable withmember this.Print() = printfn "%d %f" x y
let x2 = new SomeClass2(1, 2.0)
x2.Print()
Implementing Interfaces by Using Object Expressions
Object expressions provide a short way to implement an interface. They are useful when you do not have to create a named type, and you just want an object that supports the interface methods, without any additional methods. An object expression is illustrated in the following code.
F#
let makePrintable (x: int, y: float) =
{ new IPrintable withmember this.Print() = printfn "%d %f" x y }
let x3 = makePrintable (1, 2.0)
x3.Print()
Interface Inheritance
Interfaces can inherit from one or more base interfaces.
F#
typeInterface1=
abstractmember Method1: int -> int
typeInterface2=
abstractmember Method2: int -> int
typeInterface3=
inherit Interface1
inherit Interface2
abstractmember Method3: int -> int
typeMyClass() =
interface Interface3 withmember this.Method1(n) = 2 * n
member this.Method2(n) = n + 100member this.Method3(n) = n / 10
Implementing interfaces with default implementations
C# supports defining interfaces with default implementations, like so:
C#
using System;
namespaceCSharp
{
publicinterfaceMyDim
{
publicint Z => 0;
}
}
These are directly consumable from F#:
F#
open CSharp
// You can implement the interface via a classtypeMyType() =
member _.M() = ()
interface MyDim
let md = MyType() :> MyDim
printfn $"DIM from C#: %d{md.Z}"// You can also implement it via an object expressionlet md' = { new MyDim }
printfn $"DIM from C# but via Object Expression: %d{md'.Z}"
You can override a default implementation with override, like overriding any virtual member.
Any members in an interface that do not have a default implementation must still be explicitly implemented.
Implementing the same interface at different generic instantiations
F# supports implementing the same interface at different generic instantiations like so:
F#
typeIA<'T> =
abstractmember Get : unit -> 'TtypeMyClass() =
interface IA<int> withmember x.Get() = 1interface IA<string> withmember x.Get() = "hello"let mc = MyClass()
let iaInt = mc :> IA<int>
let iaString = mc :> IA<string>
iaInt.Get() // 1
iaString.Get() // "hello"
Izvor za ovaj sadržaj možete pronaći na GitHubu, gdje možete stvarati i pregledavati probleme i zahtjeve za povlačenjem. Dodatne informacije potražite u našem vodiču za suradnike.
Povratne informacije o proizvodu .NET
.NET je projekt otvorenog koda. Odaberite vezu za slanje povratnih informacija:
Pridružite se seriji susreta kako biste s kolegama programerima i stručnjacima izgradili skalabilna rješenja umjetne inteligencije temeljena na stvarnim slučajevima upotrebe.