Модификаторы доступа позволяют ограничить доступ к функциональности программы определенным контекстом. Модификаторы доступа применяются к модулям, определениям значений, функциям, типам, методам, свойствам и явно определенным полям (методы, свойства и явно определяемые поля будут рассмотрены в последующих статьях).
В F# есть следующие модификаторы доступа:
public: функционал доступен из любого места программы, в том числе вне проекта в других проектах
internal: функционал доступен только из текущего проекта
private: функционал доступен из типа или модуля, в котором данный функционал определен
Модификаторы указываются перед названием модулей, функций, типов, значений, но после ключевых слов module
, let
,
type
. Если модификатор доступа явным образом не указан, то уровень доступности аналогичен модификатору public
.
Чтобы подробнее разобраться в модификаторах доступа, определим два проекта F# - проект консольного приложения "HelloApp" и проект
библиотеки классов "Messages", который будет содержать файл кода Library.fs
с некоторым автосгенерированным кодом:
При этом проект библиотеки классов "Messages" подключен в проект консольного приложения "HelloApp".
Откроем файл Library.fs
в проекте Messages и изменим его код следующим образом:
namespace Messages type public MessageFuncType = unit -> unit module internal Texts = let public hello = "Hello" // доступно везде в проекте let internal goodMorning = "Good Morning" // доступно только в пределах проекта Messages let private goodEvening = "Good Evening" // доступно только в пределах модуля Text module public Funcs = let public sayHello() = printfn $"{Texts.hello}" // доступно везде let internal sayMorning() = printfn $"{Texts.goodMorning}" // доступно только в пределах проекта Messages //let public sayEvening() = printfn $"{Texts.goodEvening}" // так нельзя - не доступа к Texts.hello
Итак, в пространстве имен Messages
определено три сущности:
Тип MessageFuncType
- он имеет модификатор доступа public
, поэтому доступен из любого места программы
Модуль Texts
определяет текст сообщений - он имеет модификатор доступа internal
, поэтому доступен из любого места текущего проекта Messages
Модуль Funcs
определяет функции для вывода текста сообщений - он имеет модификатор доступа public
, поэтому доступен из любого места программы
Теперь рассмотрим модуль Funcs
.
Первая функция - sayHello()
обращается к значению hello
из модуля Texts
let public sayHello() = printfn $"{Texts.hello}"
Здесь проблем никаких нет - это поле определено с модификатором public
, поэтому достуно вне модуля Texts
в любых других модулях текущего проекта.
Вторая функция sayMorning()
обращается к значению goodMorning
из модуля Texts
let internal sayMorning() = printfn $"{Texts.goodMorning}"
Здесь то же проблем никаких нет - это поле определено с модификатором internal
, поэтому достуно вне модуля Texts
в любых других модулях текущего проекта.
Теперь возьмем закомментрированную функцию - sayEvening
let public sayEvening() = printfn $"{Texts.goodEvening}"
Эта функция обращается к значению goodEvening
из модуля Texts
, которое имеет модификатор private
, поэтому доступно только
внутри модуля Texts
Теперь изменим код файла Program.fs в главном проекте следующим образом:
open Messages // open Texts // модуль Texts недоступен open Funcs // модуль Funcs доступен let printMessage : MessageFuncType = fun()->printfn "Hi F#" // тип MessageFuncType доступен sayHello() // функция sayHello доступна // sayMorning() // функция sayMorning не доступна
Здесь мы видим, что модуль Texts
из пространства имен Messages не доступен, поскольку он определен с модификатором internal
и поэтому
доступен только внутри своего проекта.
А вот модуль Funcs
определен с модификатором public
, поэтому доступен из других проектов. Однако среди функциональности в других проектах
будет доступна только та функциональность, которая определена с модификатором . Так, мы можем в других проектах использовать его функцию
sayHello
с модификатором public
, но не можем использовать функцию sayMorning
с модификатором internal
.
И также поскольку тип MessageFuncType
имеет модификатор public
, то он также доступен из других проектов.
Если мы вернемся к проекту Messages и его модулю Texts, то можем увидеть, что вложенная сущность - значение hello
имеет модификатор
public
:
module internal Texts = let public hello = "Hello"
Но в этом модификаторе нет смысла, поскольку внешняя сущность - модуль Texts имеет модификатор internal
, что ограничивает его использование
текущим проектом. Соответственно, значение hello
также можно использовать только в рамках текущего проекта, несмотря на модификатор public
.