Instance Constructrolar
Constructor’lar objeleri initialize
ettiğimizde devreye giren özel metodlardır. Eğer obje class’ı içerisinde bir
constructor tanımlı değilse bile compiler tarafından otomatik olarak boş bir
constructor sağlanır.
Bir objenin yaratılması işlemi iki
aşamada gerçekleşir:
Birinci aşamada obje için memory’de alokasyon
gerçekleştirilir. Her obje new operator’ü kullanarak yaratılır. Bu kural için
herhangi bir exception yoktur. Bunu explicit olarak kod içerisinde
gerçekleştirebiliriz, yada compiler bunu otomatik olarak yerine getirir.
int[] MyIntArray={1,2,3,4};
int[] MyIntArray1=new
int[4]{1,2,3,4};
Yukarıdaki deklarasyonlar’ın her
ikiside aynı işi yapmaktadır.
Bir objenin yaratılmasındaki ikinci
aşamada ise constructor çağrımıdır. Constructor new ile allocate edilen
memory’i obje’ye çevirir. İki tip constructor’ın varlığından bahsedebiliriz:
static ve instance. Instance constructor’lar objelerin initialize’ı için
kullanırlırlar. Static constructor’lar ise class’ların initialize’ı için
kullanılırlar. C++’da initialize işlemi gerçekleştirmeden new operator’ü memory
allokasyonu ve yine new keyword’ü ile daha önceden allocate edilmiş memory’i
initalize etmek mümkündür. Bu ayrım C#’da mümkün değildir. Bu yöntem ile C#
memory’deki yapı okunmadan önce doğru değere atanma yapılmasını garanti etmiş
olur.
Default constructor class ile aynı isimdedir,
geriye bir değer döndürmez ve bir metod değildir (void). Default constructor’ın
herhangi bir parametresi yoktur. İstenildiği takdir de parametrik
constructor’lar tanımlanılabilir.
Constructor aynı zamanda implicit olarak
static olmayan alanları initialize işlemine tabi tutar. int, double, decimal
gibi nümerik alanlar 0’a, bool alanlar false’a Referans tipler null’a,
Struct’ların içerdiği alanların hepsi yukarıdaki yapıya uygun olarak initialize
işlemine tabi tutulurlar. Default constructor’ın bu işlmeleri yapmasının iyi
yanlarının yanı sıra dezavantajlı
yanlarıda vardır: Mesela bir tarih class’ın da yıl, ay ve gün değerlerinin
0’dan başlamasını istemeyiz. Böyle durumda kendi constructor’ımızı tanımlamamız
gerekmektedir.
Aşağıdaki örnekte default constructor
kullanan bir class ve kullanımı görülmektedir.
using System;
class Tarih
{
public short
Gun,Ay,Yil;
}
class Class1
{
[STAThread]
static void Main (string[] args)
{
Tarih
a=new Tarih();
Console.WriteLine("Yıl:{0}",a.Yil);
Console.WriteLine("Ay:{0}",a.Ay);
Console.WriteLine("gün:{0}",a.Gun);
Console.ReadLine();
}
}
Bu class’ı test ettiğimizde Ay, Gun ve
Yıl değerlerinin 0’a set edildiği rahatlıkla görülmektedir. Default
constructor’ı devre dışı bırakıp kendi constructor’ımızı yazmak istersek
kodumuz aşağıdaki şekilde olacaktır:
using System;
class Tarih
{
public short
Gun,Ay,Yil;
public Tarih()
{
Gun=1;
Ay=1;
Yil=1970;
}
}
class Class1
{
[STAThread]
static void Main(string[] args)
{
Tarih
a=new Tarih();
Console.WriteLine("Yıl:{0}",a.Yil);
Console.WriteLine("Ay:{0}",a.Ay);
Console.WriteLine("gün:{0}",a.Gun);
Console.ReadLine();
}
}
Bu kod çalıştığında ise 1.1.1970 tarihi
ile karşılaşırız. Default constructor ve kendi oluşturduğumuz constructor
arasındaki fark açık bir şekilde görülmektedir.
Constructor’lar tıpkı metod’larda olduğu
gibi overload edilebilirler. Bu sayede class’ımızın farklı initialization
işlemlerine tabi tutulması sağlanılabilir. Overload etme işlemi gayet basittir.
Class ile aynı isimde ve diğer constructor’dan farklı parametreler kabul eden
bir tanım vererek bunu sağlayabiliriz. Az önce gördüğümüz örnekteki
constructor’ı overload edecek olursak:
using System;
class Tarih
{
public short
Gun,Ay,Yil;
public Tarih()
{
Gun=1;
Ay=1;
Yil=1970;
}
public Tarih(short
Day,short Month,short
Year)
{
Gun=Day;
Ay=Month;
Yil=Year;
}
}
class Class1
{
[STAThread]
static void Main(string[] args)
{
Tarih
a=new Tarih();
Tarih
b=new Tarih(2,2,2002);
Console.WriteLine("a.Yıl:{0}",a.Yil);
Console.WriteLine("a.Ay:{0}",a.Ay);
Console.WriteLine("a.Gün:{0}",a.Gun);
Console.WriteLine("b.Yıl:{0}",b.Yil);
Console.WriteLine("b.Ay:{0}",b.Ay);
Console.WriteLine("b.Gün:{0}",b.Gun);
Console.ReadLine();
}
}
Görüldüğü gibi a ile ilgili olan tarih
1.1.1970 iken b ile ilgili olan tarih parametrik olarak ikinci constructor’a
yönlendiği için 2.2.2002 tarihini elde etmiş oluruz. Dikkat ettiyseniz birinci
constructor içerisinde de ikincisine benzer bir işlem yaptık; basit bir
assignment işlemi. Her seferinde aynı kodu yazmaktansa diğer bir yöntem ile
işimizi biraz daha kolaylaştırabiliriz birinci constructor çağrıldığında onu
ikinci constructor’a yönlendirebiliriz:
using System;
class Tarih
{
public short
Gun,Ay,Yil;
public Tarih():this(1,1,1970)
{
}
public Tarih(short
Day,short Month,short
Year)
{
Gun=Day;
Ay=Month;
Yil=Year;
}
}
class Class1
{
[STAThread]
static void Main(string[] args)
{
Tarih
a=new Tarih();
Tarih b=new
Tarih(2,2,2002);
Console.WriteLine("a.Yıl:{0}",a.Yil);
Console.WriteLine("a.Ay:{0}",a.Ay);
Console.WriteLine("a.Gün:{0}",a.Gun);
Console.WriteLine("b.Yıl:{0}",b.Yil);
Console.WriteLine("b.Ay:{0}",b.Ay);
Console.WriteLine("b.Gün:{0}",b.Gun);
Console.ReadLine();
}
}
Birinci
constructor’da yaptığımız :this(1,1,1970) yönlendirmesi ile
üç parametre kabul eden ikinci constructor’ı çağırmış olduk. Bu yönteme
initializer list adı verilmektedir. Bu noktada bilmemiz gereken bir kural ise
bir initializer list içerisinde tanımlı metod’un kendi kendini çağıramamasıdır.
Class içerisinde bazen readonly
değişkenler kullanmak istiyebiliriz. Yani değeri bir kere assign edildikten
sonra kullanıcı tarafından değiştirilmesini istemediğimiz değişkenler. Bu
şekildeki değişkenler class içerisinde aşağıdaki şekilde tanımlanılabilirler:
public readonly int
MinYil=0;
Bu tanımlama ile sonradan
değiştirilemeyecek bir değer ataması yapmış oluruz. Fakat bazı durumlarda bu
değerin class’ın yaratımı içerisinde değişmesini isteyebiliriz. Mesela class
içerisinde bir array’imiz var ve initialization sırasında bu array’in Max
range’inin belirlenmesini istiyoruz. Bu durumda bir şekilde kullanıcıya
readonly olan bu değere bir kereye mahsus bir assignment şansı vermek
zorundayız. Bu gibi durumlarda ise constructor’ları kullanmak zorunda kalırız.
Bir örnekle bakacak olursak:
using System;
class MyArray
{
public readonly int MaxRangeOfArray;
public int[] MyArr;
public MyArray(int
MaxRange)
{
MaxRangeOfArray=MaxRange;
}
public void
CreateArray()
{
MyArr=new int[MaxRangeOfArray];
}
}
class Class1
{
[STAThread]
static void Main(string[] args)
{
MyArray
a=new MyArray(1);
a.CreateArray();
a.MyArr[1]=2;
Console.ReadLine();
}
}
MaxRangeOfArray değişkenine yapmış
olduğumuz atama sadece constructor içerisinde gerçekleşebilir. Constructor
dışında herhangi bir metod içerisinde bu değişkene yapılacak atama compiler’ın
hata vermesine neden olacaktır.
Hiç yorum yok:
Yorum Gönder