F # - typy generyczne

Generics pozwalają opóźnić specyfikację typu danych elementów programistycznych w klasie lub metodzie, dopóki nie zostaną one faktycznie użyte w programie. Innymi słowy, typy ogólne umożliwiają napisanie klasy lub metody, która może działać z dowolnym typem danych.

Piszesz specyfikacje dla klasy lub metody, zastępując parametry dla typów danych. Gdy kompilator napotka konstruktora dla klasy lub wywołanie funkcji dla metody, generuje kod obsługujący określony typ danych.

W języku F # wartości funkcji, metody, właściwości i typy agregatów, takie jak klasy, rekordy i związki rozłączne, mogą być ogólne.

Konstrukcje ogólne zawierają co najmniej jeden parametr typu. Funkcje i typy ogólne umożliwiają pisanie kodu, który działa z różnymi typami bez powtarzania kodu dla każdego typu.

Składnia

Składnia do pisania konstrukcji ogólnej jest następująca -

// Explicitly generic function.
let function-name<type-parameters> parameter-list =
   function-body

// Explicitly generic method.
[ static ] member object-identifer.method-name<type-parameters> parameter-list [ return-type ] =
   method-body

// Explicitly generic class, record, interface, structure,
// or discriminated union.
type type-name<type-parameters> type-definition

Przykłady

(* Generic Function *)
let printFunc<'T> x y =
   printfn "%A, %A" x y

printFunc<float> 10.0 20.0

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

10.0, 20.0

Możesz również utworzyć funkcję ogólną, używając składni pojedynczego cudzysłowu -

(* Generic Function *)
let printFunction (x: 'a) (y: 'a) =
   printfn "%A %A" x y

printFunction 10.0 20.0

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

10.0 20.0

Należy pamiętać, że podczas korzystania z funkcji lub metod ogólnych może nie być konieczne określanie argumentów typu. Jednak w przypadku niejednoznaczności można podać argumenty typu w nawiasach ostrych, tak jak to zrobiliśmy w pierwszym przykładzie.

Jeśli masz więcej niż jeden typ, oddziel argumenty wielu typów przecinkami.

Klasa ogólna

Podobnie jak funkcje ogólne, można również pisać klasy ogólne. Poniższy przykład demonstruje to -

type genericClass<'a> (x: 'a) =
   do printfn "%A" x

let gr = new genericClass<string>("zara")
let gs = genericClass( seq { for i in 1 .. 10 -> (i, i*i) } )

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

"zara"
seq [(1, 1); (2, 4); (3, 9); (4, 16); ...]