Private Alanlar
Coddy'nin Rust Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 10 / 61.
Önceki derste her şeyi public yaptınız; struct'ı, alanlarını ve metotlarını. Ancak gerçek kapsülleme (encapsulation), verilerinize nasıl erişilebileceğini kontrol etmek anlamına gelir. Rust'ta, bir struct'ı public yaparken alanlarını private tutabilirsiniz.
Bakiyesi asla negatif olmaması gereken bir Wallet düşünün. Eğer alan genel (public) olsaydı, herkes onu herhangi bir değere ayarlayabilirdi:
// wallet.rs
pub struct Wallet {
balance: f64, // pub yok = özel (private)!
}
impl Wallet {
pub fn new(initial: f64) -> Wallet {
Wallet { balance: initial }
}
}
Wallet'ın genel (public) olduğuna, ancak balance'ın pub anahtar kelimesine sahip olmadığına dikkat edin. Bu, modül dışındaki kodun yapıcıyı (constructor) kullanarak bir Wallet oluşturabileceği, ancak balance alanını doğrudan okuyamayacağı veya değiştiremeyeceği anlamına gelir:
// main.rs
mod wallet;
use wallet::Wallet;
fn main() {
let w = Wallet::new(100.0);
// println!("{}", w.balance); // Hata! alan özeldir (private)
// w.balance = -50.0; // Hata! özel alana erişilemez
}
Bu, kapsüllemenin temelidir; struct kendi verilerini kontrol eder. Harici kod, sağladığınız metotlar üzerinden geçmelidir; bu da doğrulama, günlükleme veya başka herhangi bir mantık ekleyebileceğiniz anlamına gelir. Veriler, geçersiz durumlardan korunmuş olur.
Gelecek derslerde, getter ve setter metotları aracılığıyla bu özel verilere nasıl kontrollü erişim sağlayacağınızı öğreneceksiniz.
Görev
KolayHassas verileri bir modül içinde koruyarak kapsüllemeyi (encapsulation) gösteren bir sıcaklık sensörü sistemi kuralım.
Kodunuzu düzenlemek için iki dosya oluşturacaksınız:
sensor.rs: İki alana sahip birTemperatureSensoryapısı (struct) tanımlayın:location(String) vereading(f64). Yapı, diğer dosyalardan kullanılabilmesi için genel (public) olmalıdır, ancak her iki alanı da özel (private) tutun; harici kodlar sensörün verilerine doğrudan erişememeli veya bunları değiştirememelidir. Bir konum adı ve bir başlangıç sıcaklık okuması alan genel birnewyapıcı metodu (constructor) ekleyin.main.rs: Sensör modülünüzü dahil edin ve yapıcıyı kullanarak birTemperatureSensoroluşturun. Alanlar özel olduğu için onları doğrudan yazdıramazsınız; bunun yerine sensörün başarıyla oluşturulduğunu gösteren bir onay mesajı yazdırın.
Bu zorluk, özel alanların (private fields) temel kavramına odaklanır: yapıya erişilebilir, ancak dahili verileri korunur. Harici kod, sensörle yalnızca sağladığınız yöntemler aracılığıyla etkileşime girebilir (bu durumda sadece yapıcı metot).
Çıktınız tam olarak şu formatı izlemelidir:
Sensor created for: {location}Yazdırmak için konuma erişmek üzere, alanın kendisi özel olduğundan, new fonksiyonunuzun sensörü döndürmeden önce bu mesajı yazdırmasını sağlamanız gerekecektir.
Örneğin, "Kitchen" konumu ve 22.5 okuması ile bir sensör oluşturursanız, çıktı şöyle olacaktır:
Sensor created for: Kitchenİki girdi alacaksınız: konum adı ve başlangıç sıcaklık okuması.
Kopya kağıdı
Rust'ta, kapsülleme (encapsulation) sağlamak için bir yapıyı (struct) genel (public) yaparken alanlarını (fields) özel (private) tutabilirsiniz. Bu, harici kodun dahili verilere doğrudan erişmesini veya bunları değiştirmesini engeller.
Bir alanı özel yapmak için pub anahtar kelimesini atlamanız yeterlidir:
pub struct Wallet {
balance: f64, // pub yok = özel alan
}
impl Wallet {
pub fn new(initial: f64) -> Wallet {
Wallet { balance: initial }
}
}
Bu örnekte, Wallet geneldir (modül dışından kullanılabilir), ancak balance özeldir (dışarıdan doğrudan erişilemez).
Harici kod, genel yapıcıları (constructors) kullanarak örnekler oluşturabilir ancak özel alanları okuyamaz veya değiştiremez:
mod wallet;
use wallet::Wallet;
fn main() {
let w = Wallet::new(100.0);
// println!("{}", w.balance); // Hata! alan özeldir
// w.balance = -50.0; // Hata! özel alana erişilemez
}
Bu kapsülleme, yapının kendi verilerini kontrol etmesini sağlar ve harici kodun onunla etkileşime girmesi için sağladığınız yöntemleri kullanması gerekir.
Kendin dene
mod sensor;
use sensor::TemperatureSensor;
fn main() {
// Girdiyi oku
let mut location = String::new();
std::io::stdin().read_line(&mut location).expect("Failed to read line");
let location = location.trim().to_string();
let mut reading_str = String::new();
std::io::stdin().read_line(&mut reading_str).expect("Failed to read line");
let reading: f64 = reading_str.trim().parse().expect("Failed to parse reading");
// TODO: Yapıcıyı (constructor) kullanarak bir TemperatureSensor oluşturun
// Yeni fonksiyon, onay mesajının yazdırılmasını işleyecektir
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming bölümündeki tüm dersler
1Metotlar ve Davranış
Uygulama Bloklarına GirişSelf ParametresiDeğiştirilebilir Metotlarİlişkili FonksiyonlarBirden Fazla Uygulama BloğuMetot ZincirlemeÖzet - Dikdörtgen Eylemleri4Proje: Sanal Evcil Hayvan
Evcil Hayvanı TanımlamaEvcil Hayvanı Besleme2Kapsülleme ve Modüller
Modül TemelleriPublic Anahtar KelimesiPrivate AlanlarGetter'larSetter'larÖzet - Güvenli Kasa5Generic Yapılar
Generic Struct'larGeneric MetotlarÇoklu Generic TürlerGeneric FonksiyonlarÖzet - Koordinat Noktası8Sınırlandırıcı Olarak Trait'ler
Trait Sınırlandırıcı SözdizimiÇoklu SınırlandırıcılarWhere CümleciğiTrait'ler ile Tip DöndürmeÖzet - Generic Yazıcı11Rust'ta Tasarım Kalıpları
Newtype KalıbıKompozisyonDrop Trait'iFrom ve IntoÖzet - Smart Pointer Mock3İleri Seviye Enum'lar
Veri İçeren Enum'larEnum MetotlarıVeri Varyantlarını EşlemeOption Enum'ına Yeniden BakışÖzet - Shape Enum6Trait Tanımlama
Trait Nedir?Traitleri UygulamaVarsayılan UygulamalarVarsayılanları Geçersiz KılmaParametreli TraitlerÖzet - Media Player