Sdílet prostřednictvím


Rozšíření typů (F#)

Rozšíření typu umožňují přidat nové členy do dříve definovaného typu objektu.

// Intrinsic extension.
type typename with
   member self-identifier.member-name =
      body
   ...
   [ end ]

// Optional extension.
type typename with
   member self-identifier.member-name =
      body
   ...
   [ end ]

Poznámky

Existují dvě formy rozšíření typu, které mají mírně odlišnou syntaxi a chování.Vnitřní rozšíření je rozšíření, které se zobrazí ve stejném oboru názvů nebo modulu, ve stejném zdrojovém souboru a ve stejném sestavení (knihovna DLL nebo spustitelný soubor) jako rozšiřovaný typ.Volitelné rozšíření je rozšíření, které se objeví mimo původní modul, obor názvů a sestavení rozšiřovaného typu.Vnitřní rozšíření se zobrazí u typu, pokud je typ zkontrolován pomocí reflexe, ale volitelné rozšíření nikoli.Při otevření modulu, který obsahuje doplněk, musí být volitelné rozšíření v modulech pouze v určitém rozsahu.

V předchozí syntaxi typename představuje typ, který se rozšiřuje.Libovolný typ, který je přístupný, lze rozšířit, ale název typu musí být skutečný typ název, nikoli zkratka typu.Můžete definovat více členů v jednom rozšíření typu.Parametr self-identifier představuje instanci objektu vyvolanou stejně jako běžné členy.

Klíčové slovo end je v nenáročném syntaxi volitelné.

Členy definované podle rozšíření typu lze použít stejně jako ostatní členy typu třídy.Stejně jako ostatní členové mohou být statickými členy nebo členy instance.Tyto metody jsou také známé jako metody rozšíření; vlastnosti jsou známé jako vlastnosti rozšíření a tak dále.Volitelní členové rozšíření jsou kompilováni do statických členů, pro které je implicitně předána instance objektu jako první parametr.Působí však, jako kdyby byly členy instance nebo statickými členy podle toho, jak jsou deklarovány.Členové implicitní rozšíření jsou k dispozici jako členové typu a mohou být použity bez omezení.

Metody rozšíření nemohou být virtuální nebo abstraktní metody.Mohou přetížit jiné metody se stejným názvem, ale kompilátor dává přednost metodám nevyužívajícím rozšíření v případě dvojznačný volání.

Pokud existuje více rozšíření vnitřního typu pro jeden typ, všechny členy musí být jedinečné.Pro volitelná rozšíření typů, členové v jiných typech rozšíření stejného typu mají stejné názvy.K chybám nejednoznačnosti dojde pouze v případě, že kód klienta otevře dva různé obory, které definují stejné názvy členů.

V následujícím příkladu typ v modulu má vnitřní rozšíření typu.Pro klientský kód mimo modul se typ rozšíření zobrazí jako běžný člen typu ve všech ohledech.

module MyModule1 =

    // Define a type. 
    type MyClass() =
      member this.F() = 100

    // Define type extension. 
    type MyClass with 
       member this.G() = 200

module MyModule2 =
   let function1 (obj1: MyModule1.MyClass) =
      // Call an ordinary method.
      printfn "%d" (obj1.F())
      // Call the extension method.
      printfn "%d" (obj1.G())

Rozšíření vnitřního typu lze použít k oddělení definice typu do oddílů.To může být užitečné při správě definic velkými písmeny, například k ponechání odděleného kódu vytvořeného kompilátorem a napsaného kódu nebo seskupení kódu vytvořeného různými lidmi nebo spojeného s různými funkcemi.

Následující příklad rozšiřuje rozšíření volitelného typu typ System.Int32 o metodu rozšíření FromString, která volá statický člen Parse.Metoda testFromString ukazuje, že nový člen je volán stejně jako kterýkoli člen instance.

// Define a new member method FromString on the type Int32. 
type System.Int32 with 
    member this.FromString( s : string ) =
       System.Int32.Parse(s)

let testFromString str =  
    let mutable i = 0
    // Use the extension method.
    i <- i.FromString(str)
    printfn "%d" i

testFromString "500"

Nový člen instance se v IntelliSense zobrazí stejně, jako jakékoliv jiná metoda typu Int32, ale pouze v případě, že modul, který obsahuje rozšíření, je otevřen nebo je jinak v oboru.

Obecné metody rozšíření

Před F# 3.1 nepodporoval kompilátor F# použití rozšiřujících metod stylu C# s obecný typem proměnné, typem pole, typem n-tice, nebo typem funkce F# jako je parametr „this“.F# 3.1 podporuje používání těchto členů rozšíření.

Například v kódu F# 3.1, můžete použít rozšiřující metody s podpisy, které se podobají následující syntaxi jazyka C#:

static member Method<T>(this T input, T other)

Tento přístup je zvláště užitečný, pokud je parametr obecného typu omezen.Dále nyní můžete deklarovat členy rozšíření takto v kódu F# a definovat další, sémanticky bohatou sadu rozšiřujících metod.V F# obvykle definujete členy rozšíření, jak je popsáno v následujícím příkladu:

type seq<’T> with
    /// Repeat each element of the sequence n times
    member xs.RepeatElements(n: int) =
        seq { for x in xs do for i in 1 .. n do yield x }

Nicméně pro obecný typ nesmí být omezený typ proměnné.Nyní můžete deklarovat prvek rozšíření stylu C# v jazyce F#, chcete-li toto omezení vyřešit.Když zkombinujete tento druh prohlášení s vloženou funkcí F#, můžete představovat obecné algoritmy jako členy rozšíření.

Zvažte následující deklaraci:

[<Extension>]
type ExtraCSharpStyleExtensionMethodsInFSharp () =
    [<Extension>]
    static member inline Sum(xs: seq<’T>) = Seq.sum xs

Pomocí této deklarace, můžete napsat kód, který se podobá následujícímu příkladu.

let listOfIntegers = [ 1 .. 100 ]
let listOfBigIntegers = [ 1I to 100I ]
let sum1 = listOfIntegers.Sum()
let sum2 = listOfBigIntegers.Sum()

V tomto kódu se stejný obecný aritmetický kód uplatní pro dva typy seznamů bez přetížení definováním jednoho člena rozšíření.

Viz také

Další zdroje

Referenční dokumentace jazyka F#

Členy (F#)