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.

Zobacz też