Модификаторы доступа позволяют ограничить доступ к функциональности программы определенным контекстом. Модификаторы доступа применяются к модулям, определениям значений, функциям, типам, методам, свойствам и явно определенным полям (методы, свойства и явно определяемые поля будут рассмотрены в последующих статьях).
В 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.