Değişmezlik Kalıpları
Coddy'nin C# Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 34 / 70.
Değişmezlik (Immutability), kapsüllemeyi mantıksal uç noktasına taşır; bir nesne oluşturulduktan sonra asla değiştirilemez. Bu, verilerinizin beklenmedik bir şekilde değiştirilmesi konusunda endişelenmenize gerek kalmadığı için tüm hata kategorilerini ortadan kaldırır.
Değişmez (immutable) bir sınıf oluşturmanın en basit yolu, tüm değerleri ayarlayan bir yapıcı (constructor) ile birlikte readonly alanlar kullanmak ve hiçbir ayarlayıcı (setter) sunmamaktır:
public class Point
{
public readonly int X;
public readonly int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}Bir Point oluşturulduktan sonra koordinatları değiştirilemez. Peki ya değiştirilmiş bir versiyona ihtiyacınız olursa? Mevcut nesneyi değiştirmek yerine yeni bir nesne döndürürsünüz:
public Point Move(int deltaX, int deltaY)
{
return new Point(X + deltaX, Y + deltaY);
}Güncellenmiş değerlere sahip yeni bir nokta elde ederken orijinal nokta değişmeden kalır. Bu desen .NET genelinde kullanılır; örneğin dizeler (strings) sabittir (immutable). ToUpper() metodunu çağırdığınızda, orijinali değiştirmek yerine yeni bir dize elde edersiniz.
Değişmez (immutable) nesneler, oluşturulduktan sonra hiçbir kod onları değiştiremeyeceği için doğası gereği iş parçacığı açısından güvenlidir (thread-safe). Ayrıca, durumlarının asla beklenmedik bir şekilde değişmeyeceğini bildiğiniz için haklarında akıl yürütmek de daha kolaydır.
Görev
KolayNesnelerin oluşturulduktan sonra asla değişmeyecek şekilde nasıl tasarlanabileceğini gösteren değişmez (immutable) bir para sistemi kuralım. Her işlemin orijinali değiştirmek yerine yeni bir nesne döndürdüğü bir Money sınıfı oluşturacaksınız - bu desen, kodunuzu daha güvenli ve hakkında akıl yürütmesi daha kolay hale getirir.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
Money.cs:Financead alanı (namespace) içinde değişmez birMoneysınıfı oluşturun. Paranız şunlara sahip olmalıdır:- İki adet
readonlyalan:Amount(decimal) veCurrency(string) - Her iki değeri de ayarlayan bir yapıcı metot (constructor) - bir kez oluşturulduktan sonra, bir Money nesnesi asla değişemez
- Artırılmış tutara sahip (aynı para birimi) yeni bir
Moneynesnesi döndüren birAdd(decimal value)metodu - Azaltılmış tutara sahip (aynı para birimi) yeni bir
Moneynesnesi döndüren birSubtract(decimal value)metodu - Tutarı kur (rate) ile çarpan ve yeni para birimine sahip yeni bir
Moneynesnesi döndüren birConvert(string newCurrency, decimal rate)metodu "{Amount} {Currency}"formatında bir dize döndüren birGetDisplay()metodu
Moneyörnekleri döndürür!- İki adet
Program.cs: Ana dosyanızda, değişmezliği (immutability) iş başında gösterin. Başlangıçta birMoneynesnesi oluşturun, ardından hem orijinaline hem de sonuçlara referansları tutarak üzerinde işlemler gerçekleştirin. Bu, birden fazla işlemden sonra bile orijinalin asla değişmediğini kanıtlayacaktır.
Dört girdi alacaksınız:
- Başlangıç tutarı (decimal)
- Başlangıç para birimi (string)
- Eklenecek tutar (decimal)
- EUR'ya dönüşüm kuru (decimal)
Çıktıyı şu formatta yazdırın:
Original: {GetDisplay()}
After add: {GetDisplay()}
Original unchanged: {GetDisplay()}
Converted: {GetDisplay()}Örneğin, girdiler 100.00, USD, 50.00 ve 0.85 ise çıktı şöyle olmalıdır:
Original: 100.00 USD
After add: 150.00 USD
Original unchanged: 100.00 USD
Converted: 127.50 EURAdd() metodunu çağırdıktan sonra bile orijinal Money nesnesinin hala 100.00 USD gösterdiğine dikkat edin - işte bu değişmezliktir! Add() metodu, orijinaline dokunmadan 150.00 USD değerine sahip tamamen yeni bir nesne oluşturdu. Dönüştürme işlemi, ekleme işleminin sonucu üzerinde gerçekleştirilir.
Kopya kağıdı
Değişmezlik (Immutability), bir nesne oluşturulduktan sonra asla değiştirilemeyeceği anlamına gelir. Bu, beklenmedik veri değişiklikleriyle ilgili hataları ortadan kaldırır.
Bir yapıcı (constructor) ve ayarlayıcı (setter) içermeyen readonly alanlar kullanarak değişmez bir sınıf oluşturun:
public class Point
{
public readonly int X;
public readonly int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}Değişmez bir nesneyi değiştirmek için, mevcut olanı değiştirmek yerine yeni bir örnek döndürün:
public Point Move(int deltaX, int deltaY)
{
return new Point(X + deltaX, Y + deltaY);
}Değişmez nesnelerin faydaları:
- Oluşturulduktan sonra hiçbir kod onları değiştiremeyeceği için tasarım gereği iş parçacığı güvenlidir (thread-safe)
- Durumları asla beklenmedik şekilde değişmediği için haklarında akıl yürütmek daha kolaydır
- .NET genelinde kullanılır (örneğin, string'ler değişmezdir)
Kendin dene
using System;
using Finance;
class Program
{
public static void Main(string[] args)
{
// Girdileri oku
decimal initialAmount = Convert.ToDecimal(Console.ReadLine());
string initialCurrency = Console.ReadLine();
decimal amountToAdd = Convert.ToDecimal(Console.ReadLine());
decimal conversionRate = Convert.ToDecimal(Console.ReadLine());
// TODO: Başlangıç tutarı ve para birimi ile bir başlangıç Money nesnesi oluşturun
// TODO: GetDisplay() kullanarak orijinal parayı yazdırın
// TODO: Orijinal üzerinde Add() metodunu çağırın ve sonucu yeni bir değişkende saklayın
// TODO: Ekleme işleminden sonraki sonucu GetDisplay() kullanarak yazdırın
// TODO: Değişmediğini kanıtlamak için orijinali tekrar yazdırın
// TODO: Eklenen sonucu dönüşüm oranını kullanarak EUR birimine dönüştürün
// TODO: Dönüştürülen parayı GetDisplay() kullanarak yazdırın
}
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici Dosyalarİsim Alanları ve YönergelerSınıf ve Nesnelere Giriş'this' Anahtar KelimesiMetotlar ve ParametrelerAlanlar ve ÖzelliklerYapıcı MetotlarNesne BaşlatıcılarÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (:) Sözdizimi'base' Anahtar KelimesiVirtual ve Override Anahtar KelimeleriSealed Sınıflar'object' Temel SınıfıÖzet - Çalışan Hiyerarşisi7İleri Düzey Özellikler
Operatör Aşırı Yüklemeİndeksleyiciler (this[])ToString() Geçersiz KılmaGenişletme MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişThread-Safe SingletonFactory KalıbıObserver Kalıbı (Olaylar)Strategy Kalıbı2Özellikler ve Statik Üyeler
Otomatik Uygulanan ÖzelliklerSadece Okunur/Yazılır ÖzelliklerStatik Alanlar ve MetotlarStatik Sınıflarİfade Gövdeli Üyeler5Polimorfizm ve Arayüzler
Derleme vs Çalışma Zamanı PolimorfizmiArayüz vs Soyut SınıfÇoklu ArayüzlerBelirgin ArayüzlerUpcasting ve DowncastingÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kalıtım yerine KompozisyonGenerics (Sınıflar ve Metotlar)Delegates ve EventlerAttributes ve ReflectionIDisposable ve using İfadesiDependency Injection Temelleri11Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit Kalıbı3Sınıf Mimarisi
Örnek vs Statik Veri'readonly' ve 'const' Anahtar KelimeleriDestekleyici Alanlar (Backing Fields)Özet - Banka Hesabı Yöneticisi6Kapsülleme
Erişim BelirleyicilerKapsülleme için ÖzelliklerVeri Gizleme UygulamasıDeğişmezlik KalıplarıÖzet - Öğrenci Kayıtları