Megosztás a következőn keresztül:


Rugalmas típusok

A rugalmas típusú széljegyzetek azt jelzik, hogy egy paraméter, változó vagy érték egy adott típussal kompatibilis típussal rendelkezik, ahol a kompatibilitást az osztályok vagy interfészek objektumorientált hierarchiájában elfoglalt pozíció határozza meg. A rugalmas típusok akkor hasznosak, ha a típushierarchia magasabb típusaira való automatikus átalakítás nem történik meg, de továbbra is engedélyezni szeretné, hogy a funkció bármilyen típussal működjön a hierarchiában, vagy bármilyen olyan típussal, amely egy felületet implementál.

Syntax

#type

Megjegyzések

Az előző szintaxisban a típus egy alaptípust vagy interfészt jelöl.

A rugalmas típus egyenértékű egy olyan általános típussal, amely olyan korlátozással rendelkezik, amely az engedélyezett típusokat olyan típusokra korlátozza, amelyek kompatibilisek az alap- vagy interfésztípussal. Vagyis a következő két kódsor egyenértékű.

#SomeType

'T when 'T :> SomeType

A rugalmas típusok számos helyzetben hasznosak. Ha például magasabb rendű függvénye van (egy függvény argumentumként egy függvényt vesz fel), gyakran hasznos, ha a függvény rugalmas típust ad vissza. Az alábbi példában iterate2 egy rugalmas típus és egy sorrend argumentum használata lehetővé teszi, hogy a magasabb sorrendű függvény olyan függvényekkel működjön, amelyek sorozatokat, tömböket, listákat és bármilyen más számba írható típust hoznak létre.

Vegye figyelembe a következő két függvényt, amelyek közül az egyik egy sorozatot ad vissza, a másik pedig rugalmas típust ad vissza.

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])

Egy másik példaként tekintse meg a Seq.concat könyvtárfüggvényt :

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

Az alábbi számbavételi sorozatok bármelyikét átadhatja ennek a függvénynek:

  • Listák listája
  • Tömbök listája
  • Listák tömbje
  • Sorozatok tömbje
  • A számbavételi sorozatok bármely más kombinációja

Az alábbi kód a rugalmas típusok használatával támogatott forgatókönyvek bemutatására szolgál Seq.concat .

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

A kimenet a következő.

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; ...]

Az F#-ban, mint más objektumorientált nyelvekben, vannak olyan környezetek, amelyekben az interfészeket megvalósító származtatott típusok vagy típusok automatikusan alaptípussá vagy felülettípussá alakulnak. Ezek az automatikus átalakítások közvetlen argumentumokban történnek, de nem akkor, ha a típus alárendelt pozícióban van, egy összetettebb típus részeként, például egy függvénytípus visszatérési típusaként vagy típusargumentumként. Így a rugalmas típus jelölése elsősorban akkor hasznos, ha az alkalmazott típus egy összetettebb típus része.

Lásd még