Rust'ta C++ veya Java'daki gibi geleneksel yapıcılar yoktur, ancak genellikle tür nesneleri oluşturmak için ilişkili fonksiyonlar (genellikle new adıyla) ve sözde fabrika yöntemleri kullanılır. Bu, dilin tarihine bağlıdır; dil, güvenlik ve başlatma açıklığına özel bir önem verilerek tasarlanmıştır: sadece açıkça yazılmış ve çağrılmış bir fonksiyon, bir yapının her alanının doğru bir şekilde başlatılmasından sorumludur.
Soru Tarihçesi
Başlangıçta Rust'ta yapıların başlatılması, tüm alanların doğrudan atanmasına izin veriyordu (bu, "struct literal" sözdizimi olarak bilinir). Ancak, invariance'ı sağlamak, ayrıntıları gizlemek ve ek kontroller uygulamak için fabrika yöntemleri (impl SomeStruct { fn new(...) -> Self { ... } }) kullanma pratiği benimsendi veya şablonlar üzerinden kurumsallaşma (builder pattern) yapıldı.
Sorun
Ana görevler, kısmen başlatılmış nesnelerin oluşmasını önlemek ve geçersiz durumdaki yapıları kullanmayı imkânsız hale getirmektir. Bu özellikle karmaşık yapılar (örneğin, dosyalar, soketler vb. ile ilişkili) için kritik öneme sahiptir; burada tüm alanların manuel olarak başlatılması hatalara yol açabilir.
Çözüm
Rust'ta genellikle tamamen başlatılmış bir nesne döndüren fabrika yöntemleri oluşturulması, gerekli olduğunda doğrulama yapılması ve örneklemenin ayrıntılarını gizlemesi önerilir.
Kod Örneği:
struct User { username: String, age: u8, } impl User { pub fn new(username: String, age: u8) -> Option<Self> { if age >= 18 { Some(Self { username, age }) } else { None } } } fn main() { let user = User::new("Alice".to_string(), 20); // user: Option<User>, hata güvenli bir şekilde işlenebilir }
Ana Özellikler:
fn new) aracılığıyla uygulanır.Yapıda özel alanlar oluşturarak doğrudan örneklerin oluşturulmasını engelleyebilir miyiz?
Evet, yapı alanlarının tümü özel olarak yapılırsa ve yalnızca halka açık fabrika yöntemleri sağlanırsa, bu yapının doğrudan kendi modülü dışında başlatılması mümkün olmayacaktır.
Fabrika metodu her zaman new olarak mı adlandırılmalıdır?
Hayır, bu bir gelenektir ama zorunluluk değildir. Farklı başlatma stratejileri için "with_capacity", "from_config", "from_env" gibi isimler kullanılır.
Özel yapıcılar olabilir mi?
Evet, eğer ilişkili fonksiyon fn new(...) -> Self olarak tanımlanmışsa ve pub modifikasyonu yoksa, bu modül dışında çağrılmaz. Bu, örneğin singleton, enforce factory veya gizli başlatma uygulamalarını mümkün kılar.
Açık alanları olan bir yapının doğrudan kullanımı, fabrika metodu olmadan:
struct Connection { fd: i32, timeout: u64, } let c = Connection { fd: -1, timeout: 10 }; // fd: -1, tanımlayıcı için geçersiz!
Artılar:
Eksiler:
Özel alanların ve fabrika metodunun kullanılması:
pub struct Connection { fd: i32, timeout: u64, } impl Connection { pub fn new(fd: i32, timeout: u64) -> Option<Self> { if fd >= 0 { Some(Self { fd, timeout }) } else { None } } }
Artılar:
Eksiler: