Sınıflar (F#)
Sınıflar , özelliklere, yöntemlere ve olaylara sahip olabilecek nesneleri temsil eden türlerdir.
Sözdizimi
// Class definition:
type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] =
[ class ]
[ inherit base-type-name(base-constructor-args) ]
[ let-bindings ]
[ do-bindings ]
member-list
...
[ end ]
// Mutually recursive class definitions:
type [access-modifier] type-name1 ...
and [access-modifier] type-name2 ...
...
Açıklamalar
Sınıflar .NET nesne türlerinin temel açıklamasını temsil eder; sınıfı, F# dilinde nesne odaklı programlamayı destekleyen birincil tür kavramıdır.
Yukarıdaki söz diziminde , type-name
geçerli bir tanımlayıcıdır. isteğe type-params
bağlı genel tür parametrelerini açıklar. Köşeli ayraçlar (<
ve ) içine alınmış tür parametre adlarından ve >
kısıtlamalarından oluşur. Daha fazla bilgi için bkz . Genel VeKısıtlamalar. oluşturucu parameter-list
parametrelerini açıklar. İlk erişim değiştirici türüyle ilgili; ikinci, birincil oluşturucuyla ilgili. Her iki durumda da varsayılan değerdir public
.
Anahtar sözcüğünü kullanarak bir sınıfın temel sınıfını inherit
belirtirsiniz. Temel sınıf oluşturucu için bağımsız değişkenleri parantez içinde sağlamanız gerekir.
Bağlamaları kullanarak let
sınıf için yerel olan alanları veya işlev değerlerini bildirirsiniz ve bağlamalar için let
genel kurallara uymanız gerekir. do-bindings
bölümü, nesne oluşturma sırasında yürütülecek kodu içerir.
ek member-list
oluşturuculardan, örnek ve statik yöntem bildirimlerinden, arabirim bildirimlerinden, soyut bağlamalardan ve özellik ve olay bildirimlerinden oluşur. Bunlar Üyeler bölümünde açıklanmıştır.
identifier
İsteğe bağlı as
anahtar sözcükle kullanılan, örnek değişkenine veya tür tanımında türün örneğine başvurmak için kullanılabilen kendi tanımlayıcısına bir ad verir. Daha fazla bilgi için bu konunun devamında yer alan Kendi Kendine Tanımlayıcılar bölümüne bakın.
Tanımın başlangıcını ve end
sonunu işaretleyen anahtar sözcükler class
isteğe bağlıdır.
Birbirine başvuran türler olan karşılıklı özyinelemeli türler, aynı karşılıklı özyinelemeli işlevlerin and
olduğu gibi anahtar sözcükle birleştirilir. Bir örnek için Karşılıklı Özyinelemeli Türler bölümüne bakın.
Oluşturucular
Oluşturucu, sınıf türünün bir örneğini oluşturan koddur. Sınıfların oluşturucuları F# dilinde diğer .NET dillerinden biraz farklı çalışır. F# sınıfında, bağımsız değişkenleri tür adından sonra açıklanan parameter-list
ve gövdesi sınıf bildiriminin başındaki (ve ) bağlamalarından ve let rec
do
izleyen bağlamalardan oluşan let
birincil bir oluşturucu her zaman vardır. Birincil oluşturucunun bağımsız değişkenleri, sınıf bildirimi boyunca kapsam içindedir.
Üye eklemek için anahtar sözcüğünü new
kullanarak aşağıdaki gibi ek oluşturucular ekleyebilirsiniz:
new
(argument-list
) = constructor-body
Yeni oluşturucunun gövdesi, sınıf bildiriminin en üstünde belirtilen birincil oluşturucuyu çağırmalıdır.
Aşağıdaki örnekte bu kavram gösterilmektedir. Aşağıdaki kodda, MyClass
iki bağımsız değişken alan birincil oluşturucu ve bağımsız değişken içermeyen başka bir oluşturucu olmak üzere iki oluşturucu vardır.
type MyClass1(x: int, y: int) =
do printfn "%d %d" x y
new() = MyClass1(0, 0)
let ve do Bindings
let
Sınıf tanımındaki ve do
bağlamaları birincil sınıf oluşturucusunun gövdesini oluşturur ve bu nedenle bir sınıf örneği oluşturulduğunda çalışır. let
Bağlama bir işlevse, bir üye olarak derlenmiş olur. let
Bağlama, herhangi bir işlevde veya üyede kullanılmayan bir değerse, oluşturucuya yerel olan bir değişkene derlenmiş olur. Aksi takdirde, sınıfının bir alanında derlenmiş. İzleyen do
ifadeler birincil oluşturucuda derlenir ve her örnek için başlatma kodunu yürütür. Ek oluşturucular her zaman birincil oluşturucuyu çağırdığından, let
bağlamalar ve do
bağlamalar her zaman hangi oluşturucunun çağrıldığından bağımsız olarak yürütülür.
Bağlamalar tarafından let
oluşturulan alanlara sınıfın yöntemleri ve özellikleri boyunca erişilebilir; ancak statik yöntemler bir örnek değişkenini parametre olarak alsa bile statik yöntemlerden erişilemez. Varsa, kendi tanımlayıcısı kullanılarak bunlara erişilemez.
Kendi Tanımlayıcıları
Kendi tanımlayıcısı, geçerli örneği temsil eden bir addır. Kendi tanımlayıcıları C# veya C++ veya Me
Visual Basic'te anahtar sözcüğüne benzerthis
. Kendi tanımlayıcısının tüm sınıf tanımı için mi yoksa yalnızca tek bir yöntem için mi kapsam içinde olmasını istediğinize bağlı olarak, kendi tanımlayıcısını iki farklı şekilde tanımlayabilirsiniz.
Sınıfın tamamı için kendi kendine tanımlayıcı tanımlamak için, oluşturucu parametre listesinin kapanış parantezlerinden sonra anahtar sözcüğünü kullanın as
ve tanımlayıcı adını belirtin.
Yalnızca bir yöntem için kendi kendine tanımlayıcı tanımlamak için, üye bildiriminde, yöntem adından hemen önce ve ayırıcı olarak nokta (.) belirtin.
Aşağıdaki kod örneği, kendi tanımlayıcısı oluşturmanın iki yolunu gösterir. İlk satırda, kendi tanımlayıcısını as
tanımlamak için anahtar sözcüğü kullanılır. Beşinci satırda tanımlayıcı this
, kapsamı yöntemiyle PrintMessage
sınırlı olan bir kendi tanımlayıcısını tanımlamak için kullanılır.
type MyClass2(dataIn) as self =
let data = dataIn
do
self.PrintMessage()
member this.PrintMessage() =
printf "Creating MyClass2 with Data %d" data
Diğer .NET dillerinden farklı olarak, kendi tanımlayıcısını istediğiniz gibi adlandırabilirsiniz; , Me
veya this
gibi self
adlar ile sınırlı değildir.
anahtar sözcüğüyle as
bildirilen kendi tanımlayıcısı, temel oluşturucudan sonraya kadar başlatılmaz. Bu nedenle, temel oluşturucudan önce veya içinde kullanıldığında çalışma System.InvalidOperationException: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.
zamanı sırasında tetiklenir. Bağlamalar veya do
bağlamalar gibi let
temel oluşturucudan sonra kendi tanımlayıcısını serbestçe kullanabilirsiniz.
Genel Tür Parametreleri
Genel tür parametreleri açılı ayraçlar (<
ve >
) içinde tek tırnak işareti ve ardından bir tanımlayıcı biçiminde belirtilir. Birden çok genel tür parametresi virgülle ayrılır. Genel tür parametresi, bildirim boyunca kapsam içindedir. Aşağıdaki kod örneği, genel tür parametrelerinin nasıl belirtileceğini gösterir.
type MyGenericClass<'a>(x: 'a) =
do printfn "%A" x
Tür kullanıldığında tür bağımsız değişkenleri çıkarılır. Aşağıdaki kodda, çıkarsanan tür bir tanımlama grubu dizisidir.
let g1 = MyGenericClass(seq { for i in 1..10 -> (i, i * i) })
Devralmayı Belirtme
inherit
yan tümcesi varsa doğrudan temel sınıfı tanımlar. F# dilinde yalnızca bir doğrudan temel sınıfa izin verilir. Bir sınıfın uyguladığı arabirimler temel sınıf olarak kabul edilmez. Arabirimler, Arabirimler konusunda ele alınmıştır.
Dil anahtar sözcüğünü base
tanımlayıcı olarak ve ardından nokta (.) ve üyenin adını kullanarak türetilmiş sınıftan temel sınıfın yöntemlerine ve özelliklerine erişebilirsiniz.
Daha fazla bilgi için bkz . Devralma.
Üyeler Bölümü
Bu bölümde statik veya örnek yöntemleri, özellikler, arabirim uygulamaları, soyut üyeler, olay bildirimleri ve ek oluşturucular tanımlayabilirsiniz. Let ve do bağlamaları bu bölümde görünemez. Sınıflara ek olarak çeşitli F# türlerine üye eklenebildiği için, üyeler ayrı bir konuda ele alınmıştır: Üyeler.
Karşılıklı Özyinelemeli Türler
Döngüsel bir şekilde birbirine başvuran türler tanımladığınızda, anahtar sözcüğünü kullanarak tür tanımlarını birlikte dizelersiniz and
. anahtar and
sözcüğü, ilk tanım dışındaki tüm anahtar sözcüğünü aşağıdaki gibi değiştirir type
.
open System.IO
type Folder(pathIn: string) =
let path = pathIn
let filenameArray: string array = Directory.GetFiles(path)
member this.FileArray = Array.map (fun elem -> new File(elem, this)) filenameArray
and File(filename: string, containingFolder: Folder) =
member this.Name = filename
member this.ContainingFolder = containingFolder
let folder1 = new Folder(".")
for file in folder1.FileArray do
printfn "%s" file.Name
Çıkış, geçerli dizindeki tüm dosyaların listesidir.
Sınıflar, Birleşimler, Kayıtlar ve Yapılar Ne Zaman Kullanılır?
Aralarından seçim yapabileceğiniz çeşitli türler göz önünde bulundurulduğunda, her türün belirli bir durum için uygun türü seçmek üzere ne için tasarlandığını iyi anlamanız gerekir. Sınıflar, nesne odaklı programlama bağlamlarında kullanılmak üzere tasarlanmıştır. Nesne odaklı programlama, .NET Framework için yazılmış uygulamalarda kullanılan baskın paradigmadır. F# kodunuzun .NET Framework veya başka bir nesne odaklı kitaplıkla yakından çalışması gerekiyorsa ve özellikle kullanıcı arabirimi kitaplığı gibi nesne odaklı bir tür sisteminden genişletmeniz gerekiyorsa, sınıflar büyük olasılıkla uygundur.
Nesne odaklı kodla yakın işbirliği yapmıyorsanız veya kendi içinde bulunan ve bu nedenle nesne odaklı kodla sık sık etkileşime karşı korunan bir kod yazıyorsanız, sınıfların, kayıtların ve ayrımcı birleşimlerin bir karışımını kullanmayı düşünmelisiniz. Uygun desen eşleştirme koduyla birlikte tek, iyi düşünülmüş ayrımcı birleşim genellikle nesne hiyerarşisine daha basit bir alternatif olarak kullanılabilir. Ayrımcı birleşimler hakkında daha fazla bilgi için bkz . Ayrımcı Birleşimler.
Kayıtlar, sınıflardan daha basit olma avantajına sahiptir, ancak bir türün talepleri basitliğiyle gerçekleştirilebilecekleri aştığında kayıtlar uygun değildir. Kayıtlar temel olarak, özel eylemler gerçekleştirebilen ayrı oluşturucular olmadan, gizli alanlar olmadan ve devralma veya arabirim uygulamaları olmadan basit değer toplamalarıdır. Davranışlarını daha karmaşık hale getirmek için özellikler ve yöntemler gibi üyeler kayıtlara eklense de, kayıtta depolanan alanlar yine de basit bir değer toplama işlemidir. Kayıtlar hakkında daha fazla bilgi için bkz . Kayıtlar.
Yapılar küçük veri toplamaları için de yararlıdır, ancak .NET değer türleri oldukları için sınıflardan ve kayıtlardan farklıdır. Sınıflar ve kayıtlar .NET başvuru türleridir. Değer türlerinin ve başvuru türlerinin semantiği, değere göre geçirildiğinden farklıdır. Bu, bir parametre olarak geçirildiğinde veya bir işlevden döndürüldüklerinde bit için bit kopyalanırlar anlamına gelir. Ayrıca yığında depolanırlar veya alan olarak kullanılırlarsa yığında kendi ayrı konumlarında depolanmak yerine üst nesnenin içine eklenirler. Bu nedenle, yığına erişim yükü bir sorun olduğunda yapılar sık erişilen veriler için uygundur. Yapılar hakkında daha fazla bilgi için bkz . Yapılar.