接口 (F#)
接口指定其他类实现的相关成员集。
// 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
备注
接口声明与类声明相似,只不过未实现成员。 接口声明中的所有成员都是抽象的,这由关键字 abstract 指示。 您不会为抽象方法提供方法体。 但是,也可以通过包括单独的成员定义作为方法,与 default 关键字一起提供默认实现。 这样做等效于在其他 .NET 语言中创建基类中的虚方法。 在实现接口的类中可以重写此类虚方法。
实现接口有两种方法:使用对象表达式和使用类类型。 在任何一种情况下,类类型或对象表达式均为接口的抽象方法提供方法体。 实现过程将因实现接口的每一种类型而异。 因此,不同类型上的接口方法可能彼此不同。
在使用轻量语法时,用于标记定义的开始和结束的关键字 interface 和 end 是可选的。 如果不使用这些关键字,则编译器会通过分析您使用的构造来尝试推断出类型是一个类或还是一个接口。 如果定义成员或使用其他类语法,则类型将解释为类。
.NET 编码样式是以大写 I 开始所有接口。
通过使用类类型实现接口
通过使用 interface 关键字、接口的名称、with 关键字并在后面跟上接口成员定义,可以实现类类型中的一个或多个接口,如下面的代码所示。
type IPrintable =
abstract member Print : unit -> unit
type SomeClass1(x: int, y: float) =
interface IPrintable with
member this.Print() = printfn "%d %f" x y
接口实现是继承的,因此任何派生类不需要重新实现它们。
调用接口方法
只能通过接口来调用接口方法,而不能通过实现接口的类型的任何对象。 因此,为了调用这些方法,您可能必须通过使用 :> 或 upcast 运算符来向上转换接口类型。
如果您具有类型 SomeClass 的对象,若要调用接口方法,则必须将该对象向上转换为接口类型,如下面的代码所示。
let x1 = new SomeClass1(1, 2.0)
(x1 :> IPrintable).Print()
一种替代方法是在向上转换并调用接口方法的对象上声明一个方法,如下面的示例所示。
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()
通过使用对象表达式实现接口
对象表达式提供了一种快捷方法来实现接口。 如果您不必创建命名类型,并且只需要一个支持接口方法的对象(没有任何其他的方法),则可以使用对象表达式。 下面的代码中演示一个对象表达式。
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()
接口继承
接口可从一个或多个基接口继承。
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