Kapsülleme (Encapsulation)
Gün 2: Nesne Yönelimli Programlama (OOP) | Erişim belirleyicileri: local, protected, public
Bu derste nesne yönelimli programlamanın temel ilkelerinden biri olan kapsüllemeyi (encapsulation) öğreneceğiz. Bir sınıfın iç verilerini dış dünyadan nasıl gizleyeceğimizi ve bu verilere yalnızca kontrollü metodlar (getter/setter) üzerinden erişim sağlamayı local, protected ve public belirleyicileriyle inceleyeceğiz.
Kapsülleme Nedir?
Kapsülleme, bir sınıfın verilerini ve bu veriler üzerinde çalışan metodları bir arada tutarak iç ayrıntıları dışarıdan gizleme ilkesidir. Amaç, nesnenin durumunun ancak izin verilen ve doğrulanan yollarla değiştirilebilmesini sağlamaktır. Bu, hatalı veya tutarsız durumların oluşmasını engeller.
SystemVerilog üç erişim belirleyicisi sunar:
public(varsayılan): Üyeye her yerden erişilebilir. Belirteç yazılmazsa üyepublickabul edilir.local: Üyeye yalnızca tanımlandığı sınıfın içinden erişilebilir. Alt sınıflar bile erişemez. En katı gizlilik düzeyidir.protected: Üyeye tanımlandığı sınıf ve ondan türeyen alt sınıflardan erişilebilir, ancak sınıf dışından erişilemez.
Getter ve Setter Kalıbı
Gizli (local/protected) verilere dışarıdan erişim gerektiğinde, doğrudan erişim yerine public metodlar kullanılır:
- Getter: Veriyi okumak için (
get_balance()gibi). - Setter: Veriyi yazmak için, ama önce kontrol/doğrulama yaparak (
deposit(),withdraw()gibi). Böylece geçersiz değerler engellenir.
Kaynak Kod
// =============================================================================
// GUN 2 - Konu 4: Kapsulleme (Encapsulation): local, protected, public
// =============================================================================
class BankAccount;
// public: Disaridan erisilebilir (varsayilan)
string owner;
// local: Sadece bu sinif icinden erisilebilir
local real balance;
local int account_no;
local static int next_account = 1000;
// protected: Bu sinif ve alt siniflardan erisilebilir
protected string account_type;
protected int transaction_count;
function new(string owner, real initial_balance = 0, string acc_type = "Standard");
this.owner = owner;
this.balance = initial_balance;
this.account_type = acc_type;
this.account_no = next_account++;
this.transaction_count = 0;
endfunction
// Public getter (okuma erisimi saglar)
function real get_balance();
return balance;
endfunction
function int get_account_no();
return account_no;
endfunction
function int get_transaction_count();
return transaction_count;
endfunction
// Public setter (kontrollu yazma)
function bit deposit(real amount);
if (amount <= 0) begin
$display(" [HATA] Gecersiz miktar: %.2f", amount);
return 0;
end
balance += amount;
transaction_count++;
$display(" [+] %.2f yatirildi. Yeni bakiye: %.2f", amount, balance);
return 1;
endfunction
function bit withdraw(real amount);
if (amount <= 0 || amount > balance) begin
$display(" [HATA] Gecersiz cekim: %.2f (Bakiye: %.2f)", amount, balance);
return 0;
end
balance -= amount;
transaction_count++;
$display(" [-] %.2f cekildi. Yeni bakiye: %.2f", amount, balance);
return 1;
endfunction
function void display();
$display(" Hesap #%0d | Sahip: %s | Tip: %s | Bakiye: %.2f | Islem: %0d",
account_no, owner, account_type, balance, transaction_count);
endfunction
endclass
// Alt sinif: protected'a erisebilir, local'a erisemez
class PremiumAccount extends BankAccount;
local real credit_limit;
function new(string owner, real initial_balance, real credit_limit = 5000);
super.new(owner, initial_balance, "Premium");
this.credit_limit = credit_limit;
endfunction
// protected uyelere erisim (OK)
function void show_details();
$display(" [Premium] Tip: %s, Islem sayisi: %0d, Kredi limiti: %.2f",
account_type, transaction_count, credit_limit);
endfunction
endclass
module kapsulleme;
initial begin
BankAccount acc1;
PremiumAccount acc2;
$display("=== Kapsulleme (Encapsulation) ===\n");
// --- Public erisim ---
$display("--- Hesap Olusturma ---");
acc1 = new("Ali", 1000.0);
acc2 = new("Ayse", 5000.0, 10000.0);
acc1.display();
acc2.display();
// --- Kontrollu erisim (getter/setter) ---
$display("\n--- Islemler (Kontrollu Erisim) ---");
void'(acc1.deposit(500));
void'(acc1.withdraw(200));
void'(acc1.withdraw(99999)); // Hata: yetersiz bakiye
void'(acc1.deposit(-100)); // Hata: negatif miktar
$display("\n Bakiye (getter ile): %.2f", acc1.get_balance());
$display(" Islem sayisi: %0d", acc1.get_transaction_count());
// --- local erisim denemesi (derleme hatasi verir) ---
// acc1.balance = 999999; // HATA: 'balance' local
// acc1.account_no = 0; // HATA: 'account_no' local
// --- protected erisim (alt siniftan) ---
$display("\n--- Protected Erisim (Alt Sinif) ---");
void'(acc2.deposit(2000));
acc2.show_details();
// --- Sonuc ---
$display("\n--- Sonuc ---");
acc1.display();
acc2.display();
$display("\n=== Kapsulleme Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
BankAccountsınıfı erişim düzeyleri:ownerpublic'tir (dışarıdan erişilebilir).balance,account_novenext_accountlocal'dir (sadece sınıf içinden).account_typevetransaction_countiseprotected'tir (sınıf ve alt sınıflardan).local static next_account: Hemlocalhemstaticolduğu için sınıfa özel ortak bir sayaçtır. Her constructor'daaccount_no = next_account++ile benzersiz, ardışık hesap numaraları üretilir.- Getter metodları:
get_balance(),get_account_no()veget_transaction_count(),local/protectedalanların değerlerini dışarıya güvenli biçimde okuma erişimi sağlar. - Kontrollü setter'lar:
deposit()miktarın pozitif olduğunu,withdraw()ise miktarın geçerli ve bakiyeden küçük olduğunu doğrular. Geçersiz durumda hata yazıp0döndürür, bakiyeyi bozmaz. Bu, kapsüllemenin asıl değeridir:balance'a yalnızca kuralları geçen değerler işlenebilir. PremiumAccountalt sınıfı:BankAccount'tan türer vesuper.new(...)ile üst sınıf constructor'ını çağırır.show_details()metoduaccount_typevetransaction_count(protected) alanlarına erişebilir; ancak üst sınıfınlocalbalancealanına erişemez.- Erişim hatası örneği: Koddaki yorum satırı
acc1.balance = 999999;etkin olsaydı,balancelocalolduğu için derleme hatası verirdi. Bu, kapsüllemenin derleyici düzeyinde nasıl zorlandığını gösterir.
Önemli Noktalar
- Bir üye için belirteç yazılmazsa varsayılan
public'tir; gizlilik istiyorsanız açıkçalocalveyaprotectedyazmalısınız. localileprotectedarasındaki fark kalıtımdadır:protectedüyeler alt sınıflardan erişilebilir,localüyeler erişilemez.- Veri alanlarını gizleyip erişimi getter/setter üzerinden vermek, doğrulama (validation) eklemenize ve nesnenin tutarlılığını korumanıza imkân tanır.
- Erişim ihlalleri derleme zamanında yakalanır; bu da hataları simülasyon çalışmadan önce ortaya çıkarır.
- Benzersiz kimlik üretimi için
local staticbir sayaç kalıbı (next_account++) çok kullanışlıdır; sayaç dış müdahaleye kapalı kalır.