签名 (F#)

签名文件包含有关一组 F# 程序元素(例如类型、命名空间和模块)的公共签名的信息。 它可用于指定这些程序元素的可访问性。

备注

每个 F# 代码文件都可以有一个“签名文件”,该文件的名称与代码文件相同,但扩展名为 .fsi,而不是 .fs。 如果您直接使用命令行,则还可以将签名文件添加到编译命令行。 为了区分代码文件和签名文件,代码文件有时称为“实现文件”。 在一个项目中,签名文件应在关联的代码文件之前。

签名文件描述对应实现文件中的命名空间、模块、类型和成员。 您使用签名文件中的信息来指定对应实现文件中的哪些代码部分可从实现文件外部的代码中访问,以及哪些部分是实现文件内部使用的。 签名文件中包括的命名空间、模块和类型必须是实现文件中包括的命名空间、模块和类型的子集。 除本主题后面指出的一些例外情况外,签名文件中未列出的那些语言元素被视为是实现文件的私有元素。 如果在项目或命令行中找不到签名文件,则使用默认可访问性。

有关默认可访问性的更多信息,请参见访问控制 (F#)

在签名文件中,将不会重复每个方法或函数的类型和实现的定义, 而是会为每个方法和函数使用签名,该签名充当由模块或命名空间片段所实现的功能的完整规范。 类型签名的语法与接口和抽象类的抽象方法声明中使用的语法一样,并且,IntelliSense 和 F# 解释器 fsi.exe 在显示正确编译的输入时也会显示该语法。

如果类型签名中的信息不足,无法指明类型是否已密封或者类型是否为接口类型,则必须添加一个特性,该特性向编译器指明类型的性质。 下表中描述了用于此目的的特性。

特性

说明

[<Sealed>]

适用于没有抽象成员的类型或不应扩展的类型。

[<Interface>]

适用于作为接口的类型。

如果这些特性在签名和实现文件中的声明之间不一致,则编译器会产生错误。

使用关键字 val 可为值或函数值创建签名。 关键字 type 引入类型签名。

可以使用 --sig 编译器选项生成签名文件。 通常,您不会手动编写 .fsi 文件, 而是会使用编译器生成 .fsi 文件,将它们添加到项目(如果有项目),并通过移除不希望提供访问的方法和函数来编辑这些文件。

有若干适用于类型签名的规则:

  • 实现文件中的类型缩写不得与签名文件中没有缩写的类型匹配。

  • 记录和可区分联合必须要么公开其所有字段和构造函数,要么不公开其任何字段和构造函数,并且签名中的顺序必须与实现文件中的顺序匹配。 类可以在签名中显示其部分或全部字段和方法,也可以不显示任何字段和方法。

  • 具有构造函数的类和结构必须公开其基类的声明(inherits 声明)。 此外,具有构造函数的类和结构必须公开其所有抽象方法和接口声明。

  • 接口类型必须显示其所有方法和接口。

适用于值签名的规则如下所示:

  • 签名中的可访问性修饰符(public、internal 等)和 inline 以及 mutable 修饰符必须与实现中的这些修饰符匹配。

  • (隐式推断或显式声明的)泛型类型参数的数量必须匹配,并且泛型类型参数中的类型和类型约束必须匹配。

  • 如果使用 Literal 特性,则该特性必须同时出现在签名和实现中,并且必须为两者使用相同的文本值。

  • 签名和实现的参数模式(也称为“arity”)必须一致。

下面的代码示例显示了具有命名空间、模块、函数值和类型签名以及相应特性的签名文件的示例。 它还显示了对应的实现文件。

// Module1.fsi

namespace Library1
  module Module1 = 
    val function1 : int -> int
    type Type1 =
        new : unit -> Type1
        member method1 : unit -> unit
        member method2 : unit -> unit

    [<Sealed>]
    type Type2 = 
        new : unit -> Type2
        member method1 : unit -> unit
        member method2 : unit -> unit

    [<Interface>]
    type InterfaceType1 =  
        abstract member method1 : int -> int
        abstract member method2 : string -> unit

下面的代码演示实现文件。

namespace Library1

module Module1 =

    let function1 x = x + 1


    type Type1() =
        member type1.method1() =
            printfn "test1.method1"
        member type1.method2() =
            printfn "test1.method2"


    [<Sealed>]
    type Type2() =
        member type2.method1() =
            printfn "test1.method1"
        member type1.method2() =
            printfn "test1.method2"

    [<Interface>]
    type InterfaceType1 =
        abstract member method1 : int -> int
        abstract member method2 : string -> unit

请参见

概念

访问控制 (F#)

其他资源

F# 语言参考

编译器选项 (F#)