Obory názvů (F#)
Obor názvů umožňuje uspořádat kód do oblastí souvisejících funkcí tím, že umožňuje připojit název k seskupení prvků programu jazyka F#. Obory názvů jsou obvykle elementy nejvyšší úrovně v souborech F#.
Syntaxe
namespace [rec] [parent-namespaces.]identifier
Poznámky
Pokud chcete vložit kód do oboru názvů, musí první deklarace v souboru deklarovat obor názvů. Obsah celého souboru se pak stane součástí oboru názvů, za předpokladu, že v souboru neexistuje žádná další deklarace oborů názvů. V takovém případě se veškerý kód až do další deklarace oboru názvů považuje za první obor názvů.
Obory názvů nemohou přímo obsahovat hodnoty a funkce. Místo toho musí být hodnoty a funkce zahrnuté v modulech a moduly jsou zahrnuty do oborů názvů. Obory názvů můžou obsahovat typy a moduly.
Komentáře dokumentu XML lze deklarovat nad oborem názvů, ale jsou ignorovány. Direktivy kompilátoru lze deklarovat také nad oborem názvů.
Obory názvů lze deklarovat explicitně pomocí klíčového slova oboru názvů nebo implicitně při deklarování modulu. Pokud chcete explicitně deklarovat obor názvů, použijte klíčové slovo oboru názvů následované názvem oboru názvů. Následující příklad ukazuje soubor kódu, který deklaruje obor názvů Widgets
s typem a modulem zahrnutým v tomto oboru názvů.
namespace Widgets
type MyWidget1 =
member this.WidgetName = "Widget1"
module WidgetsModule =
let widgetName = "Widget2"
Pokud je celý obsah souboru v jednom modulu, můžete také implicitně deklarovat obory názvů pomocí klíčového module
slova a zadáním nového názvu oboru názvů do plně kvalifikovaného názvu modulu. Následující příklad ukazuje soubor kódu, který deklaruje obor názvů Widgets
a modul WidgetsModule
, který obsahuje funkci.
module Widgets.WidgetModule
let widgetFunction x y =
printfn "%A %A" x y
Následující kód je ekvivalentní předchozímu kódu, ale modul je deklarace místního modulu. V takovém případě se obor názvů musí zobrazit na vlastním řádku.
namespace Widgets
module WidgetModule =
let widgetFunction x y =
printfn "%A %A" x y
Pokud v jednom souboru v jednom nebo více oborech názvů vyžaduje více než jeden modul, musíte použít deklarace místního modulu. Pokud používáte deklarace místního modulu, nemůžete v deklaracích modulů použít kvalifikovaný obor názvů. Následující kód ukazuje soubor, který má deklaraci oboru názvů a dvě deklarace místního modulu. V tomto případě jsou moduly obsaženy přímo v oboru názvů; Neexistuje žádný implicitně vytvořený modul, který má stejný název jako soubor. Jakýkoli jiný kód v souboru, například do
vazba, je v oboru názvů, ale ne ve vnitřních modulech, takže potřebujete kvalifikovat člena widgetFunction
modulu pomocí názvu modulu.
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
Výstup tohoto příkladu je následující.
Module1 10 20
Module2 5 6
Další informace naleznete v tématu Moduly.
Vnořené obory názvů
Když vytvoříte vnořený obor názvů, musíte ho plně kvalifikovat. V opačném případě vytvoříte nový obor názvů nejvyšší úrovně. Odsazení je ignorováno v deklarací oboru názvů.
Následující příklad ukazuje, jak deklarovat vnořený obor názvů.
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"
Obory názvů v souborech a sestaveních
Obory názvů můžou zahrnovat více souborů v jednom projektu nebo kompilaci. Fragment oboru názvů výrazu popisuje část oboru názvů, která je součástí jednoho souboru. Obory názvů mohou také zahrnovat více sestavení. Obor názvů například System
zahrnuje celé rozhraní .NET Framework, které zahrnuje mnoho sestavení a obsahuje mnoho vnořených oborů názvů.
Globální obor názvů
Předdefinovaný obor názvů global
slouží k vložení názvů do oboru názvů nejvyšší úrovně .NET.
namespace global
type SomeType() =
member this.SomeMember = 0
Globální můžete použít také k odkazování na obor názvů nejvyšší úrovně .NET, například k vyřešení konfliktů názvů s jinými obory názvů.
global.System.Console.WriteLine("Hello World!")
Rekurzivní obory názvů
Obory názvů lze také deklarovat jako rekurzivní, aby se mohl vzájemně rekurzivní veškerý obsažený kód. To se provádí prostřednictvím namespace rec
. namespace rec
Použití může zmírnit některé bolesti v tom, že nedokáže zapisovat vzájemně odkazující kód mezi typy a moduly. Následuje příklad:
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
Všimněte si, že výjimka DontSqueezeTheBananaException
a třída Banana
se vzájemně odkazují. Modul BananaHelpers
a třída Banana
se navíc vzájemně odkazují. To by nebylo možné vyjádřit v jazyce F#, pokud jste odebrali rec
klíčové slovo z MutualReferences
oboru názvů.
Tato funkce je dostupná také pro moduly nejvyšší úrovně.