Bilgi Gizleme
Coddy'nin Dart Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 34 / 110.
Bilgi gizleme, kapsüllemenin (encapsulation) arkasındaki ilkedir; bir sınıfın iç işleyişini gizlemesi ve yalnızca gerekli olanı dışarıya açması fikridir. Mekanikleri (private alanlar, getter'lar, setter'lar) öğrendiniz, ancak asıl hedef, kullanımı kolay ve yanlış kullanımı zor sınıflar tasarlamaktır.
Bir kullanıcının parolasını yöneten bir sınıfı düşünün. Dahili depolama ve karma (hashing) mantığı tamamen gizlenmelidir:
class UserAccount {
String _username;
String _passwordHash;
UserAccount(this._username, String password)
: _passwordHash = _hashPassword(password);
static String _hashPassword(String password) {
return 'hashed_$password'; // Basitleştirilmiş örnek
}
bool verifyPassword(String password) {
return _passwordHash == _hashPassword(password);
}
String get username => _username;
}Dış kod, parola karmasını asla görmez veya nasıl saklandığını bilmez. Sadece verifyPassword() fonksiyonunu çağırırlar. Bu ayrım, bu sınıfı kullanan hiçbir kodu etkilemeden karma algoritmasını tamamen değiştirebileceğiniz anlamına gelir.
Temel içgörü, sınıfınızı dışarıdan içeriye doğru düşünmektir.
Kendinize şunu sorun: "Bu sınıfı (class) kullanan birinin gerçekten neye ihtiyacı var?" Sadece bunu dışarıya açın ve geri kalan her şeyi gizli (private) tutun. Bu, sınıfınızın ne yaptığı (public interface - genel arayüzü) ile bunu nasıl yaptığı (private implementation - gizli uygulaması) arasında net bir sınır oluşturur.
Görev
KolayBilgi gizlemenin (information hiding) işleyişini gösteren güvenli bir cüzdan sistemi inşa edelim. Bir kullanıcının bakiyesini ve işlem geçmişini yöneten, tüm hassas dahili ayrıntıları harici kodlardan tamamen gizli tutan dijital bir cüzdan oluşturacaksınız.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
wallet.dart: Parayı güvenli bir şekilde yöneten birWalletsınıfı oluşturun. Cüzdan, sahibinin adını herkese açık (public) olarak saklamalıdır, ancak geri kalan her şey temiz bir genel arayüzün arkasında gizlenmelidir:- Dahili bakiye ve işlem günlüğü özel (private) olmalıdır - harici kodlar parayı nasıl sakladığınızı veya takip ettiğinizi asla görmemelidir
- Özel bir yöntem, işlemleri dahili olarak kaydetmeyi yönetmelidir (
"Deposit: $50.0"veya"Withdrawal: $30.0"gibi girişleri saklayarak) - Parayı ekleyen (yalnızca miktar pozitifse) ve işlemi dahili olarak kaydeden halka açık bir
deposit(double amount)yöntemi sağlayın - Yalnızca yeterli bakiye varsa ve miktar pozitifse parayı çeken, işlemi dahili olarak kaydeden halka açık bir
withdraw(double amount)yöntemi sağlayın. Başarılı olursatrue, aksi takdirdefalsedöndürün - Mevcut bakiyeyi döndüren halka açık bir
balancegetter'ı sağlayın (salt okunur erişim) - Kaç işlemin kaydedildiğini döndüren (gerçek işlem listesini ifşa etmeden) halka açık bir
getTransactionCount()yöntemi sağlayın - En son işlem dizesini veya hiç işlem yoksa
"No transactions"döndüren halka açık birgetLastTransaction()yöntemi sağlayın - Cüzdan durumunu görüntüleyen bir
printSummary()yöntemi ekleyin
main.dart: Cüzdanınızı içe aktarın ve bilgi gizlemenin nasıl temiz ve güvenli bir arayüz oluşturduğunu gösterin:- Sahibi
"Sarah"olan bir cüzdan oluşturun 100.0yatırın50.0yatırın200.0çekmeyi deneyin ve sonuca göre"Withdrawal of 200.0: [success/failed]"yazdırın30.0çekin ve"Withdrawal of 30.0: [success/failed]"yazdırınprintSummary()yöntemini çağırın"Transaction count: [count]"yazdırın"Last transaction: [transaction]"yazdırın
- Sahibi
printSummary() yöntemi şunları yazdırmalıdır:
=== Wallet Summary ===
Owner: [ownerName]
Balance: $[balance]Harici kodun, bakiyenin nasıl saklandığını veya işlemlerin dahili olarak nasıl takip edildiğini hiç bilmeden, net ve amaçlı yöntemler aracılığıyla cüzdanla nasıl etkileşime girebildiğine dikkat edin. Uygulama detayları tamamen gizlenmiştir - cüzdanı kullanan hiçbir kodu etkilemeden işlemlerin saklanma şeklini değiştirebilirsiniz.
Beklenen çıktı:
Withdrawal of 200.0: failed
Withdrawal of 30.0: success
=== Wallet Summary ===
Owner: Sarah
Balance: $120.0
Transaction count: 3
Last transaction: Withdrawal: $30.0Kopya kağıdı
Bilgi gizleme, kapsüllemenin (encapsulation) arkasındaki ilkedir - bir sınıfın iç işleyişini gizlemek ve yalnızca gerekli olanı açığa çıkarmaktır.
Sınıfları dıştan içe doğru tasarlayın: yalnızca kullanıcıların ihtiyaç duyduğu şeyleri açığa çıkarın, geri kalan her şeyi gizli tutun. Bu, genel arayüz (sınıfın ne yaptığı) ile özel uygulama (bunu nasıl yaptığı) arasında net bir sınır oluşturur.
Bir şifre yöneticisi ile bilgi gizleme örneği:
class UserAccount {
String _username;
String _passwordHash;
UserAccount(this._username, String password)
: _passwordHash = _hashPassword(password);
static String _hashPassword(String password) {
return 'hashed_$password';
}
bool verifyPassword(String password) {
return _passwordHash == _hashPassword(password);
}
String get username => _username;
}Harici kod hiçbir zaman şifre karmasını (hash) veya depolama mekanizmasını görmez - yalnızca verifyPassword() kullanırlar. Bu, harici kodu etkilemeden dahili uygulamayı değiştirmeye olanak tanır.
Kendin dene
import 'wallet.dart';
void main() {
// TODO: "Sarah" sahibi için bir cüzdan oluşturun
// TODO: 100.0 yatırın
// TODO: 50.0 yatırın
// TODO: 200.0 çekmeyi deneyin ve sonucu yazdırın
// Format: "Withdrawal of 200.0: [success/failed]"
// TODO: 30.0 çekin ve sonucu yazdırın
// Format: "Withdrawal of 30.0: [success/failed]"
// TODO: printSummary() fonksiyonunu çağırın
// TODO: İşlem sayısını yazdırın
// Format: "Transaction count: [count]"
// TODO: Son işlemi yazdırın
// Format: "Last transaction: [transaction]"
}
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 DosyalarKütüphaneler ve ImportlarOOP'ye GirişSınıflar ve Nesnelerthis Anahtar KelimesiMetotlarÖrnek DeğişkenleriConstructor TemelleriÖzet - Basit Hesap Makinesi4Null Safety
Null Safety'ye GirişNullable ve Non-Nullable? ve ! OperatörleriLate Anahtar Kelimesi ve Null SafetyNull-Aware OperatörleriSınıflarda Null SafetyÖzet - Kullanıcı Profili Sistemi7Soyut Sınıflar ve Arayüzler
Soyut SınıflarSoyut MetotlarDart'ta ArayüzlerÖrtük ArayüzlerUygulama vs. GenişletmeÇoklu ArayüzlerÖzet - Şekil Hesaplayıcı10Koleksiyonlar ve Generic'ler
List, Set, Map Genel BakışTip Güvenli KoleksiyonlarGeneric SınıflarGeneric MetotlarGeneric KısıtlamalarIterable ve IteratorÖzet - Generic Depolama2Dart'ta Yapıcılar
Varsayılan Yapıcıİsimlendirilmiş Yapıcılarİlklendirme ListeleriSabit YapıcılarFabrika YapıcılarıYönlendiren YapıcılarÖzet - Şekil Oluşturucu5Kapsülleme
Public ve Private Üyeler_ Öneki KuralıKütüphane Düzeyinde GizlilikGetter ve Setter DetaylarıBilgi GizlemeÖzet - Öğrenci Kayıtları8Mixin'ler
Mixin'lere GirişMixin OluşturmaBirden Fazla Mixin KullanımıMixin'lerde on Anahtar KelimesiMixin vs KalıtımMixin vs ArayüzÖzet - Hayvan Sistemi11Özel Metotlar
toString() OverridehashCode ve == OverrideComparable Arayüzücall() MetodunoSuchMethod OverrideÖzet - Özel Koleksiyon14Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı17Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakter SistemiAraç Kiralama Servisi3Sınıf Özellikleri
Instance ve Statik ÜyelerFinal ve Const AlanlarLate DeğişkenlerStatik Metotlar ve AlanlarGetters ve SettersÖzet - Banka Hesabı Yöneticisi6Kalıtım
Temel Kalıtımsuper Anahtar KelimesiMetot Ezme@override Anotasyonufinal Sınıf Anahtar KelimesiYapıcı Metotlar ve KalıtımÖzet - Çalışan Hiyerarşisi9Çok Biçimlilik
Çok Biçimlilik TemelleriInterface'ler ile Çok BiçimlilikÇalışma Zamanı Tip Kontrolüis ve as OperatörleriCovariant Anahtar KelimesiÖzet - Ödeme İşlemcisi12Asenkron OOP
Futures ve async/awaitStream TemelleriStream Controller'larAsenkron KurucularSınıf Metotlarında Asenkron KullanımıÖzet - Data Fetcher15Tasarı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ıRepository Kalıbı