Encapsulation (kapsülleme)
Kapsülleme nesnelerimizde ki alanları(field) kontrollü bir şekilde dışarıya açıp kapatmamıza yarayan bir yapıdır. Nesnelerin yanlış kullanımı önlemek için erişim kısıtlaması uygular.Kapsülleme 2 şekilde uygulanır.
- Metod yardımı ile
- Property yardımı ile
C#:
class Myclass
{
private int x;
// Göndereceğimiz veriyi burada kontrol ediyoruz.
public int XGet()
{
return this.x;
}
// Dışarıdan alacağımız veriyi buradan kontrol ediyoruz.
public void XSet(int value)
{
this.x = value;
}
}
C#:
class Myclass
{
private int _x;
public int X
{
get { return _x; }
set { _x = value; }
}
}
Records
Record yapısını öğrenmemiz için önce Init-Only Properties özelliğini bilmemiz lazım.Init-Only Properties
Bu özellik bir nesnenin propery'lerine ilk değerinin verilmesi ve bu değerin değiştirilmemesini garanti altına alan bir özelliktir. Bu özellik read-only bir property yapısına benzemekte ama read-only bir property özelliğine sahip bir nesneyi oluştururken property'lerine ilk değerini veremezsin. Nesneyi oluştururken property'lere ilk değerini verebilmemiz için Init-Only Properties özelliğini kullanmalıyız. Yani Init-Only Properties, hem property'i read-only yapıyor, hemde nesneyi oluştururken property'lere ilk değer vermemizi sağlıyor.
C#:
class Program
{
static void Main(string[] args)
{
Film film = new Film()
{
adı = "Atların intikamı",
imdb = 1
};
}
}
class Film
{
public string adı { get; init; }
public int imdb { get; init; }
}
Yukarıdaki Init-Only Properties örneğidir. Gördüğünüz gibi init özelliği sayesinde property'e değeri nesneyi tanımlarken verdik ve property'ler read-only oldu.
Ayrıca readoly olarak tanımlanmış bir property'de init özelliğini kullanabiliriz.
C#:
class Film
{
private readonly string adı;
private readonly int imdb;
public string Adı
{
get { return adı; }
init { adı = value; }
}
public int Imdb
{
get { return imdb; }
init { imdb = value; }
}
}
readonly olarak tanımlanmış bir property'i init sayesinde nesne oluştururken ilk değer almasını sağlayabiliriz.
Oluşturduğumuz bir nesnenin bütün değerleri bütünsel olarak değişmemesini istiyorsak records yapısını kullanmalıyız. Record bir nesnenin tamamen sabit ve değişmez olmasını sağlayan ve bunu güvence altına alan bir yapıdır. Record sayesinde bu yapının nesnesinden ziyade sabitlediği değerleri ön plana çıkıyor. Class'larda tanımlanan bütün yapıları record'larda da tanımlayabiliriz.
C#:
class Program
{
static void Main(string[] args)
{
MyRecord x1 = new MyRecord()
{
MyProb = 5
};
MyRecord x2 = new MyRecord()
{
MyProb = 5
};
Film x3 = new Film()
{
MyProb = 5
};
Film x4 = new Film()
{
MyProb = 5
};
Console.WriteLine(x1 == x2);
Console.WriteLine(x3 == x4);
}
}
record MyRecord
{
public int MyProb { get; set; }
}
class Film
{
public int MyProb { get; set; }
}
Kod:
True
False
Örnek kullanım:
C#:
class Program
{
static void Main(string[] args)
{
MyRecord x1 = new MyRecord()
{
MyProb = 5,
MyProb1 = 4
};
}
}
record MyRecord
{
public int MyProb { get; init; }
public int MyProb1 { get; init; }
}
C#:
class Program
{
static void Main(string[] args)
{
Film f1 = new Film()
{
isim = "cehennem melekleri",
saat = "12.00",
salonNo = 2
};
Film f2 = f1 with { salonNo = 4 };
Console.WriteLine(f2.salonNo);
}
}
record Film
{
public string isim { get; init; }
public string saat { get; init; }
public int salonNo { get; init; }
}
Kod:
4
Bunu class ile yapmanın daha zahmetli bir yolu daha bulunmaktadır.
C#:
class Program
{
static void Main(string[] args)
{
Film f1 = new Film()
{
isim = "cehennem melekleri",
saat = "12.00",
salonNo = 2
};
Film f2 = f1.With(4);
Console.WriteLine(f2.salonNo);
}
}
class Film
{
public string isim { get; set; }
public string saat { get; init; }
public int salonNo { get; init; }
public Film With(int salonNO)
{
return new Film()
{
isim = this.isim,
saat = this.saat,
salonNo = salonNO
};
}
}
Positional Record
Record içerisindeki constructor, deconstructor gibi özel tanımlı metodların kullanımlarını özelleştirerek kullanılmasını sağlamaktadır.
C#:
record MyRecord(int x, int y)
{
}
C#:
class Program
{
static void Main(string[] args)
{
// Contructor'u tetikledik.
MyRecord m = new MyRecord(1, 2);
// Decontrocturu kullandık.
var (a, b) = m;
}
}
record MyRecord(int x, int y)
{
}
Yukarıda Positional record kullandığımızdan otomatik olarak x ve y propertyleri init olarak oluştu. Daha sonra nesne yaratırken parametre vererek contructor özelliğini kullandık. Hemen altında ise decontructor kullanarak nesne oluştururken verdiğimiz x ve y değerlerini a ve b değişkenlerine atadık.
Bu record'larda bulunan constructorlar overloading edilebilirler. Ama Positional recordın yarattığı constructoru tetiklemek zorunludur.
C#:
class Program
{
static void Main(string[] args)
{
// Contructor'u tetikledik.
MyRecord m = new MyRecord();
// Decontrocturu kullandık.
var (x, y) = m;
}
}
record MyRecord(int x, int y)
{
public MyRecord() : this(3, 4)
{
}
}