Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Ekstensi jenis (juga disebut augmentasi) adalah keluarga fitur yang memungkinkan Anda menambahkan anggota baru ke jenis objek yang ditentukan sebelumnya. Ketiga fitur tersebut adalah:
- Ekstensi jenis intrinsik
- Ekstensi jenis opsional
- Metode ekstensi
Masing-masing dapat digunakan dalam skenario yang berbeda dan memiliki tradeoff yang berbeda.
Sintaksis
// Intrinsic and optional extensions
type typename with
member self-identifier.member-name =
body
...
// Extension methods
open System.Runtime.CompilerServices
[<Extension>]
type Extensions() =
[<Extension>]
static member extension-name (ty: typename, [args]) =
body
...
Ekstensi jenis intrinsik
Ekstensi jenis intrinsik adalah ekstensi jenis yang memperluas jenis yang ditentukan pengguna.
Ekstensi jenis intrinsik harus didefinisikan dalam file yang sama dan di namespace atau modul yang sama dengan jenis yang diperluas. Definisi lain akan mengakibatkan mereka menjadi ekstensi jenis opsional.
Ekstensi jenis intrinsik terkadang merupakan cara yang lebih bersih untuk memisahkan fungsionalitas dari deklarasi jenis. Contoh berikut menunjukkan cara menentukan ekstensi jenis intrinsik:
namespace Example
type Variant =
| Num of int
| Str of string
module Variant =
let print v =
match v with
| Num n -> printf "Num %d" n
| Str s -> printf "Str %s" s
// Add a member to Variant as an extension
type Variant with
member x.Print() = Variant.print x
Menggunakan ekstensi jenis memungkinkan Anda memisahkan masing-masing hal berikut:
- Deklarasi jenis
Variant - Fungsionalitas untuk mencetak
Variantkelas tergantung pada "bentuk" - Cara untuk mengakses fungsionalitas pencetakan dengan object-style
.-notation
Ini adalah alternatif untuk menentukan semuanya sebagai anggota di Variant. Meskipun bukan pendekatan yang lebih baik secara inheren, itu bisa menjadi representasi fungsionalitas yang lebih bersih dalam beberapa situasi.
Ekstensi jenis intrinsik dikompilasi sebagai anggota dari jenis penambahannya, dan muncul pada jenis ketika jenis diperiksa oleh pantulan.
Ekstensi jenis opsional
Ekstensi jenis opsional adalah ekstensi yang muncul di luar modul asli, namespace, atau perakitan jenis yang diperluas.
Ekstensi jenis opsional berguna untuk memperluas jenis yang belum Anda tentukan sendiri. Contohnya:
module Extensions
type IEnumerable<'T> with
/// Repeat each element of the sequence n times
member xs.RepeatElements(n: int) =
seq {
for x in xs do
for _ in 1 .. n -> x
}
Anda sekarang dapat mengakses RepeatElements seolah-olah itu adalah anggota IEnumerable<T> selama Extensions modul dibuka dalam cakupan tempat Anda bekerja.
Ekstensi opsional tidak muncul pada jenis yang diperluas saat diperiksa oleh pantulan. Ekstensi opsional harus dalam modul, dan hanya dalam cakupan ketika modul yang berisi ekstensi terbuka atau berada dalam cakupan.
Anggota ekstensi opsional dikompilasi ke anggota statis yang instans objeknya diteruskan secara implisit sebagai parameter pertama. Namun, mereka bertindak seolah-olah mereka adalah anggota instans atau anggota statis sesuai dengan bagaimana mereka dinyatakan.
Anggota ekstensi opsional juga tidak terlihat oleh konsumen C# atau Visual Basic. Mereka hanya dapat dikonsumsi dalam kode F# lainnya.
Batasan generik ekstensi jenis intrinsik dan opsional
Dimungkinkan untuk mendeklarasikan ekstensi jenis pada jenis generik tempat variabel jenis dibatasi. Persyaratannya adalah bahwa batasan deklarasi ekstensi cocok dengan batasan jenis yang dinyatakan.
Namun, bahkan ketika batasan dicocokkan antara jenis yang dinyatakan dan ekstensi jenis, ada kemungkinan batasan disimpulkan oleh isi anggota yang diperluas yang memberlakukan persyaratan yang berbeda pada parameter jenis daripada jenis yang dinyatakan. Contohnya:
open System.Collections.Generic
// NOT POSSIBLE AND FAILS TO COMPILE!
//
// The member 'Sum' has a different requirement on 'T than the type IEnumerable<'T>
type IEnumerable<'T> with
member this.Sum() = Seq.sum this
Tidak ada cara untuk mendapatkan kode ini untuk bekerja dengan ekstensi jenis opsional:
- Apa adanya
Sum, anggota memiliki batasan yang berbeda pada'T(static member get_Zerodanstatic member (+)) dari apa yang ditentukan ekstensi jenis. - Memodifikasi ekstensi jenis agar memiliki batasan yang sama seperti
Sumtidak akan lagi cocok dengan batasan yang ditentukan padaIEnumerable<'T>. - Mengubah
member this.Summenjadimember inline this.Sumakan memberikan kesalahan bahwa batasan jenis tidak cocok.
Apa yang diinginkan adalah metode statis yang "mengapung di ruang" dan dapat disajikan seolah-olah mereka memperluas jenis. Di sinilah metode ekstensi menjadi diperlukan.
Metode ekstensi
Terakhir, metode ekstensi (terkadang disebut "anggota ekstensi gaya C#") dapat dideklarasikan dalam F# sebagai metode anggota statis pada kelas.
Metode ekstensi berguna ketika Anda ingin menentukan ekstensi pada jenis generik yang akan membatasi variabel jenis. Contohnya:
namespace Extensions
open System.Collections.Generic
open System.Runtime.CompilerServices
[<Extension>]
type IEnumerableExtensions =
[<Extension>]
static member inline Sum(xs: IEnumerable<'T>) = Seq.sum xs
Ketika digunakan, kode ini akan membuatnya muncul seolah-olah Sum didefinisikan pada IEnumerable<T>, selama Extensions telah dibuka atau berada dalam cakupan.
Agar ekstensi tersedia untuk VB.NET kode, diperlukan tambahan ExtensionAttribute pada tingkat perakitan:
module AssemblyInfo
open System.Runtime.CompilerServices
[<assembly:Extension>]
do ()
Keterangan lainnya
Ekstensi jenis juga memiliki atribut berikut:
- Jenis apa pun yang dapat diakses dapat diperpanjang.
- Ekstensi jenis intrinsik dan opsional dapat menentukan jenis anggota apa pun , bukan hanya metode. Jadi properti ekstensi juga dimungkinkan, misalnya.
- Token
self-identifierdalam sintaks mewakili instans jenis yang dipanggil, sama seperti anggota biasa. - Anggota yang diperluas dapat menjadi anggota statis atau instans.
- Jenis variabel pada ekstensi jenis harus cocok dengan batasan jenis yang dideklarasikan.
Batasan berikut juga ada untuk ekstensi jenis:
- Ekstensi jenis tidak mendukung metode virtual atau abstrak.
- Ekstensi jenis tidak mendukung metode penimpaan sebagai augmentasi.
- Ekstensi jenis tidak mendukung Parameter Jenis yang Diselesaikan Secara Statis.
- Ekstensi Jenis Opsional tidak mendukung konstruktor sebagai augmentasi.
- Ekstensi jenis tidak dapat didefinisikan pada singkatan jenis.
- Ekstensi jenis tidak valid untuk
byref<'T>(meskipun dapat dinyatakan). - Ekstensi jenis tidak valid untuk atribut (meskipun dapat dideklarasikan).
- Anda dapat menentukan ekstensi yang membebani metode lain dengan nama yang sama, tetapi pengompilasi F# memberikan preferensi pada metode non-ekstensi jika ada panggilan ambigu.
Terakhir, jika beberapa ekstensi jenis intrinsik ada untuk satu jenis, semua anggota harus unik. Untuk ekstensi jenis opsional, anggota dalam ekstensi jenis yang berbeda ke jenis yang sama dapat memiliki nama yang sama. Kesalahan ambiguitas hanya terjadi jika kode klien membuka dua cakupan berbeda yang menentukan nama anggota yang sama.