Bir öncekli yazimizda vb.net programlama dili kullanilarak Yordamlara farkli sayida parametre göndermek, Özyineli (Recursive Yordamlar), Main yordamindan bahsetmistik. Simdi ise Yapicilar(Constructors), Yikicilar(Destructors) Özellikler(Properties) indexsleyiciler(indexers) göz atacagiz.
1-k Yapicilar (Constructors)
Bir sinif ve üyeleri dogrudan kullanmak yerine ondan bir nesne üretip onu kullaniriz; nesne olusturuldugu zaman nesneyi hazirlayan ve sekillendiren özel yordamlara yapici(constructor) yordam denilir. Yapicilar, disaridan parametre alabilen, ancak geriye deger döndürmeyen yordamlardir. Siniftan nesne olusturdugumuz zaman yapilamasi istenilen islemleri bu yordamlar araciligiyla gerçeklestiririz. Yapicilar, nesneleri olusturmak için kullanilan new operatörüyle tetiklenir.
Eger programci tarafindan sinifin yapici yordami tanimlanmissa derleyici tarafindan varsayilan yapici denilen kurucu bir yordam olusturur. Bu sadece new operatoru dogru calissin diye olusturulmus parametresiz ve genel degiskenleri baslangiç durumuna getiren yordamdir. Eger programci, bir yordam yazmissa derleyici varsayilan yordami olusturmaz.
Yapicilar new() isminde bir yordam olarak tanimlanir. Disaridan erisilebilecegi için bu yordamin public olarak tanimlanmasi gerekir. Bazi durumlarda programcinin siniftan bir instance olusturmasini engellemek için yapici, private olarak tanimlanabilir. Asagidaki kodlarda Siparis sinifinin yapicisi tanimlanmistir.
Module nyp
Sub Main()
End Sub
Class Siparis
Public kdv As Double
Sub New()
' Yapilacak islemler
End Sub
End Module
Yapicilarin parametre alabilen yordamlar oldugunu söylemistik. Örnekte sinifin yapicisi UrunGrupId isminde bir parametreye sahiptir.
Module nyp
Sub Main()
Dim ObjUrun As New urun(2)
Console.WriteLine("KDV degeri : {0}", ObjUrun.kdv)
Dim hesap As Integer = ObjUrun.FiyatHesapla
Console.WriteLine("Fonksiyon Sonucu : {0}", hesap)
Console.ReadLine()
End Sub
Class urun
Public kdv As Double
Sub New(ByVal UrunGrupid As Byte)
If UrunGrupid = 1 Then kdv = 200
If UrunGrupid = 2 Then kdv = 150
End Sub
Function FiyatHesapla() As Integer
Dim fiyat As Double = 500
Return fiyat + kdv
End Function
End Class
End Module
1-l Yikicilar (Destructors)
Olusturulan bir nesnenin yüklendigi bellekten yok edilmeden hemen önce çalisan yordamlara yikici (destructor) yordam denir. "Garbage Collection" yapisinda oldugu gibi CLR, bellekte bulunan ancak kendisine ait referanslarin olmadigi (yok oldugu) nesneleri otomatik olarak bellekten siler. Böylece olusturulan yeni nesnelere yer ayrilmis olur.
Nesne bellekten silinmeden önce son kez yapacagi islemleri ( açik olan bir database baglantisini kapatmak gibi ) yikici yordamlarda tanimlariz. Yikicilar Finalize() isminde bir yordam olarak tanimlanir. Finalize() yordamina disaridan erisilmedigi için Protected olarak nitelendirilir.
Protected Overrides Sub Finalize()
' Yapilacak islemler
End Sub
Asagidaki örnekte Araba sinifi tanimlanmis ve bu siniftan yüksek sayida nesne olusturularak GC’nin devreye girmesi saglanmistir. Nesnelerin silinmeye hazir olmasi için nesne üretilmesi sinifin kendi içinde yapilmistir.
Imports System.Diagnostics
Module yikiciyordam
Sub Main()
Dim oAraba As New Araba(0)
For index = 1 To 10
oAraba.NesneOlustur(index)
Next
GC.Collect()
Console.ReadLine()
End Sub
Private Class Araba
Private sayac As Integer = 0
' Yapici Yordam Tanimlayalim
Public Sub New(ByVal x As Integer)
sayac = x
End Sub
' O anda yok olacak sekilde bir nesne olusturalim
Public Sub NesneOlustur(ByVal x As Integer)
Dim oAraba As New Araba(x)
End Sub
' Destructor tanimlayalim
Protected Overrides Sub Finalize()
Try
Console.WriteLine("{0} nolu araba yok ediliyor !", sayac)
Finally
MyBase.Finalize()
End Try
End Sub
End Class
End Module
Yikici Yordamlarin genel özellikleri sunlardir;
- Bu yordam programci tarafindan degil, ancak GC tarafindan çalistirilir.
- Bu yordam yeniden yüklenmez ( Overload) ve miras (inherit) alinamaz. Bu yüzden bir sinif en fazla bir tane yikici yordama sahip olur.
- Bu yordam parametre alamaz ve geriye deger döndüremez.
- Bu yordam sadece class türlerinde tanimlanir; structure türünde tanimlanamaz.
1-m Özellikler ve Indeksleyiciler
Özellikler (Property), sinifin içindeki degiskenleri yönetmemizi ve degiskenler set() veya get() edilirken bazi özel islemler yapmamizi saglayan küçük kod parçaciklaridir. Indeksleyiciler ise özelliklerin özel bir türü olup nesnenin içerdigi bazi degerlerin diziler gibi listelenmesini saglayan yapilardir.
Özellikler, bir sinifin içerisindeki yerel veya genel alanlari yöneten, yönlendiren ve onlara ait özellikleri belirleyen yordamlardir. Genel olarak, programcinin ilgili alani dogrudan kullanmasi yerine, o alana bu yordamlar üzerinden erisilmesini saglamak için gelistirilir. Örnegin sinif içindeki bir degiskene deger atamadan önce degerin belirli kistaslara uyup uymadigini kontrol etmek isteyebilir; ayrica deger atamadan sonra belirli islemlerin yapilmasina ihtiyaç duyabiliriz. Bu durumda programci ile degisken arasinda bir yordam tanimlariz. Bu yordama özellik denir. Özellikler, kontrollere ait özelliklerin belirlendigi alanlardir. Örnegin bir Textbox nesnesinin yazi rengini belirlemek için ilgili özelligini ( ForeColor ) kullanmak gerekir.
Akilli alanlar ( smarts fields ) olarakta bilinen özellikler get() ve set() adli iki alt yordamdan olusur. Alici olarakta tanimlanan get blogu özellikten veri okumaya çalisildiginda, ayarlayici olarak tanimlanan set blogu ise özellige veri yazilmaya çalisildiginda devreye girer. Aslindan özellikler bulunduklari siniflarin get() ve set() fonksiyonlaridir. Özellikler Property sözcügüyle tanimlanir.
Public Property ÖzellikAdi() As Tipi
Get
' Dönecek Deger
End Get
Set(value As Integer)
' Degisecek Deger
End Set
End Property
Özellige gönderilen deger value ifadesiyle temsil edilir. Derleyici Value degerine özelligin kontrol ettigi degiskenle iliskilendirir.
Özelliklerin degerini degistirdigi degiskenin herkez tarafindan dogrudan erisebilir nitelikte olmamasi yani private olmasi gerekir. Çünkü o degiskenlere ancak özellik üzerinden erisilmelidir.
Asagidaki örnekte x degiskeninin çift olmasi istenmektedir. Eger tek sayi girilirse degiskenin degerine sifir atanmalidir. Bu kontrolü yapmak üzere Xindegeri isimli özellik tanimlanmistir.
Module getset
Sub Main()
Dim objislem As New islem
objislem.Xindegeri() = 8
Console.WriteLine("x sin degeri : {0}", objislem.Xindegeri)
objislem.Xindegeri() = 5
Console.WriteLine("x sin degeri : {0}", objislem.Xindegeri)
Console.ReadLine()
End Sub
Public Class islem
Private x As Integer
Public Property Xindegeri() As Integer
Get
Return x
End Get
Set(value As Integer)
If value Mod 2 = 0 Then
x = value
Else
Console.WriteLine("Lütfen çift deger giriniz !")
x = 0
End If
End Set
End Property
End Class
End Module
Görüldügü gibi yerel olarak tanimlanmis x degiskenine dogrudan degil, Xindegeri isimli property üzerinden dolayli olarak erisilmistir. X degiskenine sadece Xindegeri özelligi erisebilir. X degiskenin degerini okumak için Xindegeri özelliginin get() alanindan yararlandik. Set() alanida gelen degeri kontrol etmis eger çift sayi ise x’e degerin kendisini atamis degilse 0 degerini atamistir. Böylece islem isimli bir bilesene ait veriyi koruma altina almis olduk. (encapsulate)
Birde girilen sayinin karesini alan bir uygulama yapalim;
Module getset2
Sub Main()
Console.Write("Lütfen bir deger giriniz")
Dim sayi As Integer = Console.ReadLine()
Dim objislem As New islem
objislem.karesi() = sayi
Console.WriteLine(sayi & " Sayisinin karesi : {0}", objislem.karesi)
Console.ReadLine()
End Sub
Public Class islem
Private x As Integer
Public Property karesi() As Integer
Get
Return x
End Get
Set(value As Integer)
If value = 0 Or value = 1 Then
Console.WriteLine("Girilen deger {0} olamaz !", value)
Else
x = value * value
End If
End Set
End Property
End Class
End Module
Özellikler her zaman get() veya set() alanlarini içermek zorunda degildir. Bu tamamen özelligin karakterine baglidir. Içinde hem get() hemde set() alanini bulunduran özellikler "okunabilir" ve "yazilabilir" niteliktedir. Sadece okunabilir veya yazilabilir özelliklerde gerçeklestirmek mümkündür. Bir özelligi sadece okunabilir yapmak için ReadOnly sözcügü, sadece yazilabilir yapmak için WriteOnly sözcügü kullanilir.
Public WriteOnly Property DogumYili() As Integer
'Degisecek Degerler
End Property
Public ReadOnly Property Yas As Integer
' Dönecek Degerler
End Property
Asagidaki örnekte Uye isimli sinifin içinde salt yazilir Dogumyili ve salt okunur yas isimli özellikler tanimlanmistir. Amacimiz kullanicinin dogum yilini ögrenip kaç yasinda oldugunu bildirmektir.
NET 2.0 ile birlikte özelligin içerisindeki getter ve setter yordamlarina özel erisim tanimlayici tanimlama imkani geldi.
Module getset3
Sub Main()
Console.WriteLine("Lütfen Dogum Yilinizi Giriniz")
Dim islem As New yashesapla
islem.DogumYili = Console.ReadLine()
Console.WriteLine("Su anki yasiniz {0} dur.", islem.Yas)
Console.ReadLine()
End Sub
Public Class yashesapla
Dim dogumyil As Integer
Public WriteOnly Property DogumYili() As Integer
Set(value As Integer)
dogumyil = value
End Set
End Property
Public ReadOnly Property Yas As Integer
Get
Return Now.Year - dogumyil
End Get
End Property
End Class
End Module
1-n Indeksleyiciler (indexers)
Yazim biçimi olarak özelliklere benzeyen indeksleyiciler bir nesnenin dizi gibi indekslenmesini saglar. Özellikler degisken tabanli indeksleyiciler ise dizi tabanli erisim imkani verir. Bir siniftan örnekledigimiz nesneye indeks degeri girerek, sinif içerisindeki bir dizi veya koleksiyonun o indeksteki elemanina erisebilir. Indeksleyiciler Default Property ifadesiyle tanimlanir.
Default Public Property XYZ(ByVal index As Integer) As String
Get
' indexs ile belirtilen degeri döndürür.
End Get
Set(value As String)
' indexs ile belirtilen degeri ayarla
End Set
End Property
Bildirimdeki eleman-türü ifadesi indeksleyicinin eristigi koleksiyon türüdür. indeks parametresi tam sayi olmak zorunda degildir; fakat tam sayi olmasi beklenir. indeksleyicilerin en önemli özelligi isimleriyle çagirilmiyor olmasidir. Bu yuzden özelliklere verdigimiz isim bir anlam ifade etmeyecektir. Asagida üyeler isminde bir dizi ve bunu yoneten bir indeksleyici tanimlanmistir.
Module indexleyiciler1
Sub Main()
Dim ObjUye As New Uye
Console.WriteLine("Dizinin 2. elemani {0}", ObjUye.XYZ(2))
Console.ReadLine()
End Sub
Public Class Uye
Private uyeler() As String = {"Mert", "Root", "Finch"}
Default Public Property XYZ(ByVal index As Integer) As String
Get
Return uyeler(index)
End Get
Set(value As String)
uyeler(index) = value
End Set
End Property
End Class
End Module
Sadece bu sekilde kullanilmasi biraz anlamsiz gelebilir. Çünki indeksleyici kullanmadanda dizi yönetilebilirdi. Fakat dizi hakkinda bilgi sahibi olunmadan onun kullanilmasi beklenemez.
Sinifin içene Uzunluk isminde bir özellik tanimlayarak yerel dizinin büyüklügüne eriselim. Böylece programci dizinin kapasitesinide ögrenmis olsun.
Module indexleyiciler2
Sub Main()
Dim dizi As New Uyeler
Console.WriteLine("Dizinin 2. elemani : {0}", dizi.XYZ(2))
Console.WriteLine()
For i = 0 To dizi.DiziUzunluk
Console.WriteLine(i & " Elemani {0}", dizi.XYZ(i))
Next
Console.ReadLine()
End Sub
Public Class Uyeler
Private uyeler() As String = {"Okan", "Elanur", "Elif"}
Default Public Property XYZ(ByVal index As Integer) As String
Get
If index < 0 Or index >= uyeler.Count Then
Console.WriteLine("0 ile {0} arasinda index giriniz.", uyeler.Count - 1)
Else
Return uyeler(index)
End If
End Get
Set(value As String)
If index < 0 Or index >= uyeler.Count Then
Console.WriteLine("0 ile {0} arasinda index giriniz.", uyeler.Count - 1)
Else
uyeler(index) = value
End If
End Set
End Property
Public ReadOnly Property DiziUzunluk As Integer
Get
Return uyeler.Count
End Get
End Property
End Class
End Modul
Indeksleyiciyi diziyle iliskilendirildigi için ve dizinin de birden fazla boyutu oldugu olabilecegi için indeksleyici birden fazla parametre alabilir. Özellikler hem get() hem de set() yordamlarini içermek zorunda degildir. Sadece get() yordamina sahip olup salt okunur, sadece set() yordamina sahip olup salt yazilir olabilirler.
Dipnot : Örneklerde görüldügü gibi indexer içeren bir nesnenin dizi elemanlari üzerinde klasik for döngüsüyle islem yapiyorz. Dizinin elemanlarina bu haliyle foreach yöntemiyle erisemeyiz. Indexer yapisi foreach yöntemini desteklemez. Bu yöntemin desteklenmesi için indexer kullanmak yerinde IEnumerable arabirimi kullanilir. Indeksleyiciler özelliklerden farkli olarak yeniden yüklenebilir; ancak statik olarak tanimlanmazlar.