Przestrzenie nazw (F#)
Przestrzeń nazw umożliwia organizowanie kodu w obszarach powiązanych funkcji, umożliwiając dołączanie nazwy do grupowania elementów programu F#. Przestrzenie nazw są zazwyczaj elementami najwyższego poziomu w plikach języka F#.
Składnia
namespace [rec] [parent-namespaces.]identifier
Uwagi
Jeśli chcesz umieścić kod w przestrzeni nazw, pierwsza deklaracja w pliku musi zadeklarować przestrzeń nazw. Zawartość całego pliku staje się następnie częścią przestrzeni nazw, pod warunkiem, że w pliku nie istnieje żadna inna deklaracja przestrzeni nazw. Jeśli tak jest, to cały kod do momentu, aż następna deklaracja przestrzeni nazw zostanie uznana za znajdującą się w pierwszej przestrzeni nazw.
Przestrzenie nazw nie mogą zawierać bezpośrednio wartości i funkcji. Zamiast tego wartości i funkcje muszą być uwzględnione w modułach, a moduły są zawarte w przestrzeniach nazw. Przestrzenie nazw mogą zawierać typy i moduły.
Komentarze dokumentu XML można zadeklarować powyżej przestrzeni nazw, ale są ignorowane. Dyrektywy kompilatora można również zadeklarować powyżej przestrzeni nazw.
Przestrzenie nazw można zadeklarować jawnie za pomocą słowa kluczowego przestrzeni nazw lub niejawnie podczas deklarowania modułu. Aby jawnie zadeklarować przestrzeń nazw, użyj słowa kluczowego przestrzeni nazw, a następnie nazwy przestrzeni nazw. W poniższym przykładzie przedstawiono plik kodu, który deklaruje przestrzeń nazw Widgets
z typem i modułem dołączonym do tej przestrzeni nazw.
namespace Widgets
type MyWidget1 =
member this.WidgetName = "Widget1"
module WidgetsModule =
let widgetName = "Widget2"
Jeśli cała zawartość pliku jest w jednym module, możesz również zadeklarować przestrzenie nazw niejawnie przy użyciu module
słowa kluczowego i podać nową nazwę przestrzeni nazw w w pełni kwalifikowanej nazwie modułu. W poniższym przykładzie pokazano plik kodu, który deklaruje przestrzeń nazw Widgets
i moduł WidgetsModule
, który zawiera funkcję.
module Widgets.WidgetModule
let widgetFunction x y =
printfn "%A %A" x y
Poniższy kod jest odpowiednikiem poprzedniego kodu, ale moduł jest deklaracją modułu lokalnego. W takim przypadku przestrzeń nazw musi być wyświetlana we własnym wierszu.
namespace Widgets
module WidgetModule =
let widgetFunction x y =
printfn "%A %A" x y
Jeśli więcej niż jeden moduł jest wymagany w tym samym pliku w co najmniej jednej przestrzeni nazw, należy użyć lokalnych deklaracji modułów. W przypadku używania deklaracji modułów lokalnych nie można użyć kwalifikowanej przestrzeni nazw w deklaracjach modułu. Poniższy kod przedstawia plik z deklaracją przestrzeni nazw i dwoma lokalnymi deklaracjami modułów. W takim przypadku moduły są zawarte bezpośrednio w przestrzeni nazw; Nie ma niejawnie utworzonego modułu, który ma taką samą nazwę jak plik. Każdy inny kod w pliku, taki jak do
powiązanie, znajduje się w przestrzeni nazw, ale nie w modułach wewnętrznych, więc należy zakwalifikować element członkowski widgetFunction
modułu przy użyciu nazwy modułu.
namespace Widgets
module WidgetModule1 =
let widgetFunction x y =
printfn "Module1 %A %A" x y
module WidgetModule2 =
let widgetFunction x y =
printfn "Module2 %A %A" x y
module useWidgets =
do
WidgetModule1.widgetFunction 10 20
WidgetModule2.widgetFunction 5 6
Dane wyjściowe tego przykładu są następujące.
Module1 10 20
Module2 5 6
Aby uzyskać więcej informacji, zobacz Moduły.
Zagnieżdżone przestrzenie nazw
Podczas tworzenia zagnieżdżonej przestrzeni nazw należy ją w pełni zakwalifikować. W przeciwnym razie utworzysz nową przestrzeń nazw najwyższego poziomu. Wcięcia są ignorowane w deklaracjach przestrzeni nazw.
W poniższym przykładzie pokazano, jak zadeklarować zagnieżdżonych przestrzeni nazw.
namespace Outer
// Full name: Outer.MyClass
type MyClass() =
member this.X(x) = x + 1
// Fully qualify any nested namespaces.
namespace Outer.Inner
// Full name: Outer.Inner.MyClass
type MyClass() =
member this.Prop1 = "X"
Przestrzenie nazw w plikach i zestawach
Przestrzenie nazw mogą obejmować wiele plików w jednym projekcie lub kompilacji. Fragment przestrzeni nazw terminu opisuje część przestrzeni nazw, która jest zawarta w jednym pliku. Przestrzenie nazw mogą również obejmować wiele zestawów. Na przykład System
przestrzeń nazw zawiera cały program .NET Framework, który obejmuje wiele zestawów i zawiera wiele zagnieżdżonych przestrzeni nazw.
Globalna przestrzeń nazw
Wstępnie zdefiniowaną przestrzeń nazw global
służy do umieszczania nazw w przestrzeni nazw najwyższego poziomu platformy .NET.
namespace global
type SomeType() =
member this.SomeMember = 0
Można również użyć globalnego, aby odwołać się do przestrzeni nazw platformy .NET najwyższego poziomu, na przykład, aby rozwiązać konflikty nazw z innymi przestrzeniami nazw.
global.System.Console.WriteLine("Hello World!")
Cykliczne przestrzenie nazw
Przestrzenie nazw można również zadeklarować jako rekursywne, aby umożliwić wzajemnie rekursywny cały zawarty kod. Odbywa się to za pomocą polecenia namespace rec
. Korzystanie z programu namespace rec
może złagodzić niektóre problemy, ponieważ nie może pisać wzajemnie odwołującego się kodu między typami i modułami. Poniżej przedstawiono przykład:
namespace rec MutualReferences
type Orientation = Up | Down
type PeelState = Peeled | Unpeeled
// This exception depends on the type below.
exception DontSqueezeTheBananaException of Banana
type Banana(orientation : Orientation) =
member val IsPeeled = false with get, set
member val Orientation = orientation with get, set
member val Sides: PeelState list = [ Unpeeled; Unpeeled; Unpeeled; Unpeeled] with get, set
member self.Peel() = BananaHelpers.peel self // Note the dependency on the BananaHelpers module.
member self.SqueezeJuiceOut() = raise (DontSqueezeTheBananaException self) // This member depends on the exception above.
module BananaHelpers =
let peel (b: Banana) =
let flip (banana: Banana) =
match banana.Orientation with
| Up ->
banana.Orientation <- Down
banana
| Down -> banana
let peelSides (banana: Banana) =
banana.Sides
|> List.map (function
| Unpeeled -> Peeled
| Peeled -> Peeled)
match b.Orientation with
| Up -> b |> flip |> peelSides
| Down -> b |> peelSides
Należy pamiętać, że wyjątek DontSqueezeTheBananaException
i klasa Banana
odwołują się do siebie nawzajem. Ponadto moduł BananaHelpers
i klasa Banana
również odwołują się do siebie. Nie byłoby to możliwe do wyrażenia w języku F# w przypadku usunięcia rec
słowa kluczowego MutualReferences
z przestrzeni nazw.
Ta funkcja jest również dostępna dla modułów najwyższego poziomu.