Tür Genişletmeleri (F#)
Tür uzantıları önceden tanımlanmış nesne türü için yeni üye eklemenizi sağlar.
// Intrinsic extension.
type typename with
member self-identifier.member-name =
body
...
[ end ]
// Optional extension.
type typename with
member self-identifier.member-name =
body
...
[ end ]
Notlar
Biraz farklı bir sözdizimi ve çalışma biçimine sahip tür uzantılarının iki biçimi vardır.Dahili uzantı aynı ad alanında veya modülde, aynı kaynak dosyasında ve genişletilmekte olan türle aynı derlemede (DLL veya yürütülebilir dosya) görünen bir uzantıdır.İsteğe bağlı uzantı orijinal modülün, ad alanının veya genişletilmekte olan türün derlemesinin dışında görünen uzantıdır.Tür yansıma tarafından incelendiğinde, iç uzantılar tür üzerinde görünür ancak isteğe bağlı uzantılar görünmez.İsteğe bağlı uzantılar, modüller halinde olmalıdır ve sadece uzantıyı içeren modül açıkken kapsamdadır.
Önceki sözdiziminde, typename genişletilmekte olan türü temsil eder.Erişilebilen tüm türler genişletilebilir ancak tür adı gerçek tür adı olmalıdır, tür kısaltması olmamalıdır.Bir tür uzantısında birden çok üye tanımlayabilirsiniz.self-identifier, sıradan üyelerdeki gibi, çağrılan nesnenin örneğini temsil eder.
end anahtar sözcüğü, basit sözdiziminde isteğe bağlıdır.
Tür uzantıları içinde tanımlanmış üyeler tıpkı diğer üyeler gibi sınıf türünde kullanılabilir.Diğer üyeler gibi bunlar statik veya örnek üyeler olabilir.Bu yöntemler genişletme yöntemleri olarak da bilinir; özellikler genişletme özellikleri olarak bilinir, vb.İsteğe bağlı uzantı üyeleri, nesne örneğinin örtülü olarak ilk parametre olarak geçirildiği statik üyeler için derlenmiştir.Ancak bunlar bildirildikleri şekle göre örnek üyeleri ta da statik üyelermiş gibi davranır.Dolaylı uzantı üyeleri türün üyeleri olarak eklenir ve kısıtlama olmadan kullanılabilir.
Uzantı yöntemleri sanal ya da soyut yöntemler olamaz.Aynı ada sahip diğer yöntemleri aşırı yükleyebilirler, ancak belirsiz bir çağrı olması durumunda, derleyici tercihi uzantısı olmayan yöntemlere verir.
Tel tür için birden çok gerçek tür uzantısı varsa, tüm üyelerin benzersiz olması gerekir.İsteğe bağlı türü uzantıları için farklı tür uzantılardaki aynı türe üyelerin aynı adları olabilir.Belirsizlik hataları yalnızca istemci kodu aynı üye adını tanımlayan iki farklı kapsamı açarsa oluşur.
Aşağıdaki örnekte, bir modül içindeki türün gerçek tür uzantısı vardır.Modülün dışındaki istemci kodunun yanında, her bakımdan türün düzenli bir üyesi olarak tür uzantısı görünür.
module MyModule1 =
// Define a type.
type MyClass() =
member this.F() = 100
// Define type extension.
type MyClass with
member this.G() = 200
module MyModule2 =
let function1 (obj1: MyModule1.MyClass) =
// Call an ordinary method.
printfn "%d" (obj1.F())
// Call the extension method.
printfn "%d" (obj1.G())
Tür tanımını bölümlere ayırmak için iç tür uzantıları kullanabilirsiniz.Bu, derleyicinin ürettiği kodu ve yazılmış kodu ayrı tutmak veya farklı kişiler tarafından oluşturulan ya da farklı işlevlerle ilişkili kodları gruplandırmak için büyük tür tanımlarını yönetmede de yararlı olabilir.
Aşağıdaki örnekte, bir isteğe bağlı uzantısı türünü System.Int32 türüne, statik üye Parse aramasında kullanılan genişletme yöntemi ile FromString genişletir.testFromString yöntemi, yeni üyenin başka herhangi bir örnek üyesi gibi çağrıldığını belirtir.
// Define a new member method FromString on the type Int32.
type System.Int32 with
member this.FromString( s : string ) =
System.Int32.Parse(s)
let testFromString str =
let mutable i = 0
// Use the extension method.
i <- i.FromString(str)
printfn "%d" i
testFromString "500"
Yeni örnek üye, yalnızca uzantıyı içeren modül açık veya başka bir şekilde kapsam içinde olduğunda, IntelliSense'te Int32 türünün başka bir yöntemi gibi görünür.
Genel Uzantı Yöntemleri
F# 3.1'den önce F# derleyicisi; genel tür değişkeniyle, dizi türüyle, tanımlama grubu türüyle veya "this" parametresi olarak F# işlev türüyle C# stili genişletme yöntemlerinin kullanımını desteklemedi.F# 3.1, bu uzantı üyelerinin kullanımını destekler.
Örneğin F# 3.1 kodunda uzantı yöntemlerini C#'de aşağıdaki söz dizimine benzeyen imzalarla kullanabilirsiniz:
static member Method<T>(this T input, T other)
Genel tür parametresi kısıtlı olduğunda bu yaklaşım özellikle yararlıdır.Ayrıca artık F# kodunda yer alan bunun gibi uzantı üyelerini bildirebilir ve ilave, semantik olarak zengin bir uzantı yöntemi kümesi tanımlayabilirsiniz.F# programında, genellikle uzantı üyelerini aşağıdaki örnekte gösterildiği gibi tanımlayın:
type seq<’T> with
/// Repeat each element of the sequence n times
member xs.RepeatElements(n: int) =
seq { for x in xs do for i in 1 .. n do yield x }
Ancak bir genel tür için tür değişkeni kısıtlanmayabilir.Artık, bu sınırlara yakın çalışmak için C# stili uzantı üyesini F# içinde bulabilirsiniz.Bu tür bir bildirimi F# satır içi özelliğiyle birleştirdiğinizde, genel algoritmaları uzantı üyeleri olarak gösterebilirsiniz.
Aşağıdaki bildirimi inceleyin:
[<Extension>]
type ExtraCSharpStyleExtensionMethodsInFSharp () =
[<Extension>]
static member inline Sum(xs: seq<’T>) = Seq.sum xs
Bu bildirimi kullanarak, aşağıdaki örneğe benzer bir kod yazabilirsiniz.
let listOfIntegers = [ 1 .. 100 ]
let listOfBigIntegers = [ 1I to 100I ]
let sum1 = listOfIntegers.Sum()
let sum2 = listOfBigIntegers.Sum()
Bu kodda, aynı genel aritmetik kod aşırı yüklemeden, tek bir uzantı üyesi tanımlayarak, iki tür listesine uygulanır.