Sdílet prostřednictvím


Flexibilní typy

Flexibilní poznámka k typu označuje, že parametr, proměnná nebo hodnota má typ, který je kompatibilní se zadaným typem, kde kompatibilita je určena umístěním v objektově orientované hierarchii tříd nebo rozhraní. Flexibilní typy jsou užitečné konkrétně v případě, že k automatickému převodu na typy vyšší v hierarchii typů nedojde, ale přesto chcete, aby funkce fungovaly s libovolným typem v hierarchii nebo s jakýmkoli typem, který implementuje rozhraní.

Syntaxe

#type

Poznámky

V předchozí syntaxi typ představuje základní typ nebo rozhraní.

Flexibilní typ je ekvivalentní obecnému typu, který má omezení, které omezuje povolené typy na typy kompatibilní se základním typem nebo typem rozhraní. To znamená, že následující dva řádky kódu jsou ekvivalentní.

#SomeType

'T when 'T :> SomeType

Flexibilní typy jsou užitečné v několika typech situací. Pokud máte například funkci vyššího pořadí (funkci, která funkci přebírá jako argument), je často užitečné, aby funkce vracela flexibilní typ. V následujícím příkladu použití flexibilního typu s argumentem sekvence umožňuje iterate2 funkci vyššího pořadí pracovat s funkcemi, které generují sekvence, pole, seznamy a jakýkoli jiný výčtový typ.

Vezměte v úvahu následující dvě funkce, z nichž jedna vrací sekvenci, druhou z nich vrací flexibilní typ.

let iterate1 (f : unit -> seq<int>) =
    for e in f() do printfn "%d" e
let iterate2 (f : unit -> #seq<int>) =
    for e in f() do printfn "%d" e

// Passing a function that takes a list requires a cast.
iterate1 (fun () -> [1] :> seq<int>)

// Passing a function that takes a list to the version that specifies a
// flexible type as the return value is OK as is.
iterate2 (fun () -> [1])

Jako další příklad zvažte funkci knihovny Seq.concat :

val concat: sequences:seq<#seq<'T>> -> seq<'T>

Této funkci můžete předat některou z následujících výčtových sekvencí:

  • Seznam seznamů
  • Seznam polí
  • Pole seznamů
  • Pole sekvencí
  • Jakákoli jiná kombinace výčtových sekvencí

Následující kód používá Seq.concat k předvedení scénářů, které můžete podporovat pomocí flexibilních typů.

let list1 = [1;2;3]
let list2 = [4;5;6]
let list3 = [7;8;9]

let concat1 = Seq.concat [ list1; list2; list3]
printfn "%A" concat1

let array1 = [|1;2;3|]
let array2 = [|4;5;6|]
let array3 = [|7;8;9|]

let concat2 = Seq.concat [ array1; array2; array3 ]
printfn "%A" concat2

let concat3 = Seq.concat [| list1; list2; list3 |]
printfn "%A" concat3

let concat4 = Seq.concat [| array1; array2; array3 |]
printfn "%A" concat4

let seq1 = { 1 .. 3 }
let seq2 = { 4 .. 6 }
let seq3 = { 7 .. 9 }

let concat5 = Seq.concat [| seq1; seq2; seq3 |]

printfn "%A" concat5

Výstup je následující.

seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]

V jazyce F# jsou stejně jako v jiných objektově orientovaných jazycích kontexty, ve kterých jsou odvozené typy nebo typy implementované rozhraní automaticky převedeny na základní typ nebo typ rozhraní. Tyto automatické převody se vyskytují v přímých argumentech, ale ne v případě, že je typ v podřízené pozici, jako součást složitějšího typu, jako je návratový typ typu funkce nebo jako argument typu. Zápis flexibilního typu je proto primárně užitečný, pokud je typ, na který ho používáte, součástí složitějšího typu.

Viz také