Builder Berbasis Keadaan Tipe
Nyatakan validitas dalam sistem tipe.
Builder Berbasis Keadaan Tipe adalah pelajaran Learn Rust Coding gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Learn Rust Coding, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Learn Rust Coding mencakup 4 pelajaran total.
Masalah pada Builder Biasa
Builder biasa memungkinkan Anda memanggil build() kapan saja, bahkan sebelum bidang yang wajib diisi ditetapkan. Data yang hilang kemudian muncul sebagai kepanikan saat runtime atau sebagai Err.
Builder dengan status tipe memindahkan pemeriksaan itu ke waktu kompilasi: melupakan langkah wajib akan langsung menyebabkan kegagalan kompilasi.
Menyandikan Status dalam Tipe
Caranya adalah membuat builder generik terhadap tipe penanda yang mewakili langkah-langkah yang sudah selesai. Saat Anda menetapkan setiap bidang, tipe builder tersebut berubah.
Metode build() hanya tersedia setelah setiap penanda wajib mencapai status "set".
struct Missing;
struct Set;Builder Generik terhadap Penanda
Berikan parameter tipe kepada builder untuk status setiap bidang wajib. PhantomData membawa penanda tersebut tanpa menyimpan data nyata.
use std::marker::PhantomData;
struct ReqBuilder<H, U> {
url: Option<String>,
method: Option<String>,
_state: PhantomData<(H, U)>,
}Status Awal
Konstruktor mengembalikan builder dengan setiap penanda wajib bernilai Missing. Pada tahap ini build() belum ada, sehingga sistem tipe mengetahui bahwa objek tersebut belum lengkap.
impl ReqBuilder<Missing, Missing> {
fn new() -> Self {
ReqBuilder { url: None, method: None, _state: PhantomData }
}
}Mengubah Penanda
Setter menggunakan builder lama dan mengembalikan builder baru dengan penanda bidang tersebut diubah menjadi Set. Penanda lainnya dipertahankan dengan membiarkan parameter tipenya tetap generik.
impl<U> ReqBuilder<Missing, U> {
fn url(self, url: &str) -> ReqBuilder<Set, U> {
ReqBuilder { url: Some(url.to_string()),
method: self.method, _state: PhantomData }
}
}Perubahan Kedua
Menetapkan metode bekerja dengan cara yang sama, yaitu mengubah penanda kedua dari Missing menjadi Set dan membiarkan penanda pertama tetap.
impl<H> ReqBuilder<H, Missing> {
fn method(self, m: &str) -> ReqBuilder<H, Set> {
ReqBuilder { url: self.url,
method: Some(m.to_string()), _state: PhantomData }
}
}build() Hanya Saat Semua Terisi
Yang terpenting, build() hanya diimplementasikan untuk ReqBuilder<Set, Set>. Status lainnya tidak memiliki metode tersebut, sehingga pemanggilannya gagal dikompilasi.
Di dalamnya, pemanggilan unwrap tidak mungkin menyebabkan kepanikan karena tipe membuktikan bahwa kedua bidang tersedia.
struct Request { url: String, method: String }
impl ReqBuilder<Set, Set> {
fn build(self) -> Request {
Request { url: self.url.unwrap(), method: self.method.unwrap() }
}
}Menggabungkan Semuanya
Rangkaian yang benar dikompilasi tanpa masalah karena setiap pemanggilan mengarahkan builder menuju ReqBuilder<Set, Set>, tempat build() tersedia.
fn demo() -> Request {
ReqBuilder::new()
.url("https://example.com")
.method("GET")
.build()
}Kesalahan Kompilasi yang Diinginkan
Lewati langkah wajib dan kompilator akan menolak kode tersebut. Memanggil build() pada ReqBuilder<Set, Missing> melaporkan "no method named build", sehingga kelalaian tertangkap sebelum program dijalankan.
// ReqBuilder::new().url("x").build();
// error: no method named `build` found for
// ReqBuilder<Set, Missing>Versi yang Dapat Dijalankan Secara Mandiri
Program minimal ini menggunakan satu bidang wajib untuk menunjukkan seluruh perubahan dari awal hingga akhir. Program ini dikompilasi dan mencetak nilai yang telah dibuat.
use std::marker::PhantomData;
struct Missing; struct Set;
struct B<N> { name: Option<String>, _s: PhantomData<N> }
impl B<Missing> {
fn new() -> Self { B { name: None, _s: PhantomData } }
fn name(self, n: &str) -> B<Set> {
B { name: Some(n.to_string()), _s: PhantomData }
}
}
impl B<Set> {
fn build(self) -> String { self.name.unwrap() }
}
fn main() {
let v = B::new().name("prod").build();
println!("built: {}", v);
}Biaya dan Pertukaran
Builder dengan status tipe memberikan jaminan pada waktu kompilasi tanpa biaya runtime, karena penanda dihapus. Imbalannya adalah mekanisme tipe yang lebih rumit dan blok impl yang bertambah secara kombinatorial saat jumlah bidang wajib meningkat.
Gunakan pola ini hanya untuk API yang mengharuskan pembuatan yang belum lengkap mustahil secara desain.
Pemeriksaan Singkat
Identifikasi hal yang sebenarnya menjamin kelengkapan dalam builder dengan status tipe.
Rangkuman
Builder dengan status tipe menyandikan setiap langkah wajib sebagai parameter tipe penanda yang dibawa oleh PhantomData. Setter menggunakan builder dan mengembalikan tipe baru dengan salah satu penanda diubah menjadi Set.
Karena build() hanya diimplementasikan untuk status yang semuanya Set, melupakan suatu langkah menjadi kesalahan kompilasi, bukan kepanikan saat runtime, dan semuanya tanpa biaya runtime.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Builder Berbasis Keadaan Tipe” gratis?
Ya — teks lengkap “Builder Berbasis Keadaan Tipe” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Learn Rust Coding, upgrade ke CoddyKit PRO. Kursus Learn Rust Coding mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Builder Berbasis Keadaan Tipe”?
Nyatakan validitas dalam sistem tipe. Kamu berlatih Learn Rust Coding dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Learn Rust Coding?
Tidak diperlukan pengalaman sebelumnya. Learn Rust Coding di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Builder Berbasis Keadaan Tipe” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Learn Rust Coding ini?
Ya. Setiap pelajaran Learn Rust Coding menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Pola Builder
- Pola Newtype
- Builder Berbasis Keadaan Tipe
- Ergonomi Deref dan Pembungkus