F # - Generics

Generics cho phép bạn trì hoãn việc đặc tả kiểu dữ liệu của các phần tử lập trình trong một lớp hoặc một phương thức, cho đến khi nó thực sự được sử dụng trong chương trình. Nói cách khác, generic cho phép bạn viết một lớp hoặc phương thức có thể hoạt động với bất kỳ kiểu dữ liệu nào.

Bạn viết các đặc tả cho lớp hoặc phương thức, với các tham số thay thế cho kiểu dữ liệu. Khi trình biên dịch gặp một hàm tạo cho lớp hoặc một lệnh gọi hàm cho phương thức, nó sẽ tạo ra mã để xử lý kiểu dữ liệu cụ thể.

Trong F #, các giá trị hàm, phương thức, thuộc tính và các kiểu tổng hợp như lớp, bản ghi và các kết hợp phân biệt có thể là chung.

Các cấu trúc chung chứa ít nhất một tham số kiểu. Các hàm và kiểu chung cho phép bạn viết mã hoạt động với nhiều loại mà không cần lặp lại mã cho từng loại.

Cú pháp

Cú pháp để viết một cấu trúc chung như sau:

// 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

Ví dụ

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

printFunc<float> 10.0 20.0

Khi bạn biên dịch và thực thi chương trình, nó sẽ tạo ra kết quả sau:

10.0, 20.0

Bạn cũng có thể tạo một hàm chung chung bằng cách sử dụng cú pháp dấu ngoặc kép -

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

printFunction 10.0 20.0

Khi bạn biên dịch và thực thi chương trình, nó sẽ tạo ra kết quả sau:

10.0 20.0

Xin lưu ý rằng khi bạn sử dụng các hàm hoặc phương thức chung, bạn có thể không phải chỉ định các đối số kiểu. Tuy nhiên, trong trường hợp không rõ ràng, bạn có thể cung cấp các đối số kiểu trong dấu ngoặc nhọn như chúng ta đã làm trong ví dụ đầu tiên.

Nếu bạn có nhiều loại, thì bạn phân tách nhiều đối số loại bằng dấu phẩy.

Lớp chung

Giống như các hàm chung, bạn cũng có thể viết các lớp chung. Ví dụ sau đây chứng minh điều này -

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

Khi bạn biên dịch và thực thi chương trình, nó sẽ tạo ra kết quả sau:

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