Jenis Fleksibel

Anotasi jenis fleksibel menunjukkan bahwa parameter, variabel, atau nilai memiliki jenis yang kompatibel dengan jenis yang telah ditentukan, saat kompatibilitasnya ditentukan oleh posisi dalam hierarki kelas atau antarmuka yang berorientasi objek. Jenis fleksibel berguna khususnya ketika konversi otomatis ke jenis yang lebih tinggi dalam hierarki jenis tidak terjadi tetapi Anda masih ingin mengaktifkan fungsionalitas Anda untuk dapat berfungsi dengan jenis apa pun dalam hierarki atau jenis apa pun yang menerapkan antarmuka.

Sintaks

#type

Keterangan

Dalam sintaks sebelumnya, jenis mewakili jenis dasar atau antarmuka.

Jenis fleksibel setara dengan jenis generik yang memiliki batasan yang memberi batasan pada jenis yang diizinkan ke jenis yang kompatibel dengan jenis dasar atau jenis antarmuka. Artinya, dua baris kode berikut ini adalah setara.

#SomeType

'T when 'T :> SomeType

Jenis fleksibel berguna dalam beberapa jenis situasi. Misalnya, ketika Anda memiliki fungsi urutan yang lebih tinggi (fungsi yang mengambil fungsi sebagai argumen), sering kali ini berguna untuk meminta fungsi mengembalikan jenis yang fleksibel. Dalam contoh berikut, penggunaan jenis fleksibel dengan argumen urutan di iterate2 memungkinkan fungsi dengan urutan yang lebih tinggi untuk bekerja dengan fungsi yang menghasilkan urutan, array, daftar, dan jenis enumerasi lainnya.

Pertimbangkan dua fungsi berikut, salah satunya mengembalikan urutan, yang lain mengembalikan jenis fleksibel.

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

Sebagai contoh lain, pertimbangkan fungsi pustaka Seq.concat :

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

Anda dapat meneruskan salah satu urutan enumerasi berikut ke fungsi ini:

  • Daftar dari daftar
  • Daftar dari array
  • Array dari daftar
  • Array dari urutan
  • Kombinasi lain dari urutan enumerasi

Kode berikut menggunakan Seq.concat untuk menunjukkan skenario yang dapat Anda dukung dengan menggunakan jenis fleksibel.

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

Outputnya sebagai berikut.

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

Dalam F#, seperti dalam bahasa berorientasi objek lainnya, ada konteks saat jenis atau jenis turunan yang menerapkan antarmuka secara otomatis dikonversi ke jenis dasar atau jenis antarmuka. Konversi otomatis ini terjadi dalam argumen langsung, tetapi tidak terjadi ketika jenis berada dalam posisi subordinat, sebagai bagian dari jenis yang lebih kompleks seperti jenis pengembalian dari jenis fungsi, atau sebagai argumen jenis. Dengan demikian, notasi jenis fleksibel terutama sangat berguna ketika jenis yang Anda terapkan adalah bagian dari jenis yang lebih kompleks.

Lihat juga