Сигнатуры (F#)
В файле сигнатур содержатся сведения об открытых сигнатурах ряда элементов программы на языке F#, таких как типы, пространства имен и модули.Файл сигнатур можно использовать для указания доступности этих элементов программы.
Заметки
Для каждого файла кода F# может иметься файл сигнатур — файл с тем же именем, что и файл кода, но с расширением FSI вместо FS.Файлы сигнатур также могут добавляться в командную строку компиляции, если используется непосредственно командная строка.Для различения файлов кода и файлов сигнатур файлы кода иногда называют файлами реализации.В проекте файл сигнатур должен предшествовать связанному с ним файлу кода.
Файл сигнатур описывает пространства имен, модули, типы и члены в соответствующем файле реализации.Информацию в файле сигнатур можно использовать для указания того, к каким частям кода в соответствующем файле реализации возможен доступ из кода, находящегося за пределами файла реализации, и какие части являются внутренними по отношению к файлу реализации (т. е. доступны только из него).Пространства имен, модули и типы, включаемые в файл сигнатур, должны представлять собой подмножество имен пространств, модулей и типов, включаемых в файл реализации.За некоторыми исключениями, рассмотренными ниже в этом разделе, языковые элементы, не присутствующие в файле сигнатур, считаются закрытыми по отношению к файлу реализации.Если в проекте или в командной строке не найден файл сигнатуры, используется доступность по умолчанию.
Дополнительные сведения о доступности по умолчанию см. в разделе Управление доступом (F#).
В файле сигнатур не нужно повторять определение типов и реализаций для каждого метода или функции.Вместо этого для каждого метода и функции используется сигнатура, выступающая в качестве полной спецификации функциональности, реализуемой фрагментом модуля или пространства имен.Синтаксис сигнатуры типа идентичен используемому в объявлениях абстрактных методов в интерфейсах и абстрактных классах; он также отображается IntelliSense и интерпретатором языка F# (fsi.exe) при выводе правильно скомпилированных входных данных.
Если в сигнатуре типа нет достаточной информации для определения того, является ли тип запечатанным или типом интерфейса, нужно добавить атрибут, по которому компилятор сможет определить природу типа.Используемые с этой целью атрибуты приведены в следующей таблице.
Атрибут |
Описание |
---|---|
[<Sealed>] |
Для типа, который не имеет абстрактных членов или не должен быть расширен. |
[<Interface>] |
Для типа, являющегося интерфейсом. |
Компилятор выдает ошибку, если атрибуты в сигнатуре и в объявлении в файле реализации не соответствуют друг другу.
Для создания сигнатуры для значения или значения функции используется ключевое слово val.Сигнатура типа предваряется ключевым словом type.
Сформировать файл сигнатур можно с помощью параметра --sig компилятора.Как правило, вручную 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