シグネチャ (F#)
シグネチャ ファイルには、F# の一連のプログラム要素 (型、名前空間、モジュールなど) のパブリック シグネチャに関する情報が格納されます。このファイルを使用して、それらのプログラム要素のアクセシビリティを指定できます。
解説
F# コード ファイルごとにシグネチャ ファイルを作成できます。シグネチャ ファイルは、コード ファイルと同じ名前になりますが、拡張子は .fs ではなく、.fsi です。コマンド ラインを直接使用している場合は、シグネチャ ファイルをコンパイル コマンド ラインに追加することもできます。コード ファイルとシグネチャ ファイルを区別するために、コード ファイルを実装ファイルと呼ぶこともあります。プロジェクトでは、シグネチャ ファイルは関連付けられたコード ファイルの前に置かれる必要があります。
シグネチャ ファイルには、対応する実装ファイル内の名前空間、モジュール、型、およびメンバーを記述します。シグネチャ ファイル内の情報を使用して、対応する実装ファイル内のコードのどの部分に実装ファイルの外部のコードからアクセスできるか、また、どの部分が実装ファイルに対して内部的であるかを指定します。シグネチャ ファイルに含まれる名前空間、モジュール、および型は、実装ファイルに含まれる名前空間、モジュール、および型のサブセットである必要があります。このトピックで後述する一部の例外を除き、シグネチャ ファイル中の一覧にない言語要素は、実装ファイルに対してプライベートであると見なされます。プロジェクトまたはコマンド ラインでシグネチャ ファイルが見つからない場合、既定のアクセシビリティが使用されます。
既定のアクセシビリティの詳細については、「アクセス制御 (F#)」を参照してください。
シグネチャ ファイルでは、各メソッドまたは関数の型および実装の定義を繰り返さないでください。代わりに、各メソッドおよび関数のシグネチャを使用します。シグネチャは、モジュールまたは名前空間フラグメントによって実装される機能の完全な仕様として機能します。型シグネチャの構文は、インターフェイスおよび抽象クラス内の抽象メソッド宣言で使用する構文と同じであり、IntelliSense によっても表示されます。また、適切にコンパイルされた入力を表示する場合には、F# インタープリター fsi.exe によっても表示されます。
型がシールされているかどうか、または型がインターフェイス型であるかどうかを示すための十分な情報が型シグネチャ内に存在しない場合、型の性質を示す属性をコンパイラに追加する必要があります。この目的で使用する属性を次の表に示します。
属性 |
Description |
---|---|
[<Sealed>] |
抽象メンバーを持たない型、または拡張しない型。 |
[<Interface>] |
インターフェイスである型。 |
シグネチャと実装ファイル内の宣言の間で属性が一貫していない場合、コンパイラはエラーを生成します。
値または関数値のシグネチャを作成するには、val キーワードを使用します。type キーワードは、型シグネチャを導入します。
シグネチャ ファイルを生成するには、--sig コンパイラ オプションを使用します。一般に、.fsi ファイルを手動で記述することはありません。代わりに、コンパイラを使用して .fsi ファイルを生成し、プロジェクトが存在する場合は、そのプロジェクトに .fsi ファイルを追加します。そして、.fsi ファイルを編集して、アクセスできないようにするメソッドおよび関数を削除します。
型シグネチャには、いくつかの規則があります。
実装ファイル内の型略称が、シグネチャ ファイル内の省略しない型と一致しないようにする必要があります。
レコードおよび判別共用体では、フィールドおよびコンストラクターのすべてを公開するか、まったく公開しないようにする必要があります。また、シグネチャ内の順序は、実装ファイル内の順序と一致している必要があります。クラスでは、フィールドおよびメソッドの一部またはすべてをシグネチャで公開するか、まったく公開しないようにすることができます。
コンストラクターがあるクラスおよび構造体では、基本クラスの宣言 (inherits 宣言) を公開する必要があります。また、コンストラクターがあるクラスおよび構造体では、抽象メソッドおよびインターフェイス宣言のすべてを公開する必要があります。
インターフェイス型では、メソッドおよびインターフェイスのすべてを公開する必要があります。
値シグネチャの規則は、次のとおりです。
シグネチャ内のアクセシビリティ用の修飾子 (public、internal など) と inline 修飾子および mutable 修飾子は、実装内のそれらの修飾子と一致する必要があります。
暗黙で推論されるか、または明示的に宣言されるジェネリック型パラメーターの数は一致する必要があります。また、ジェネリック型パラメーターの型および型制約は一致する必要があります。
Literal 属性を使用する場合は、この属性がシグネチャと実装の両方に存在し、両方で同じリテラル値を使用する必要があります。
シグネチャおよび実装のパラメーターのパターン (アリティとも呼ばれます) は、一貫している必要があります。
名前空間、モジュール、関数値、および型シグネチャと適切な属性を含むシグネチャ ファイルの例を、次のコード例に示します。また、対応する実装ファイルも示します。
// 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