Error Rust E0616: field of struct is private (field privat)
E0616 artinya: field yang kamu minta memang ada, tapi field itu privat di modul tempat struct-nya didefinisikan. Kamu boleh memegang struct-nya, hanya saja tidak boleh mengintip ke dalamnya. Error ini dialami semua orang yang pertama kali memindahkan struct ke modulnya sendiri, dan semua orang yang mengetik v.len padahal maksudnya v.len(). Perbaikannya biasanya cukup dengan memanggil method. Halaman ini bagian dari Penjelasan error compiler Rust.
Pesan error-nya
Section titled “Pesan error-nya”error[E0616]: field `balance` of struct `Account` is private --> src/main.rs:16:50 |16 | println!("{} has {}", account.owner, account.balance); // ❌ field privat | ^^^^^^^ private fieldCompiler bilang field balance milik struct Account itu privat, dan panahnya menunjuk ke field tersebut.
Ini program yang menghasilkan error tersebut:
mod bank { pub struct Account { pub owner: String, balance: u64, // privat }
impl Account { pub fn new(owner: &str) -> Account { Account { owner: owner.to_string(), balance: 0 } } }}
fn main() { let account = bank::Account::new("Ferris"); println!("{} has {}", account.owner, account.balance); // ❌ field privat}Error yang sama muncul dalam beberapa variasi:
| Apa yang kamu tulis | Apa kata rustc | Perbaikan |
|---|---|---|
account.balance |
field `balance` of struct `Account` is private |
Perbaikan 2 atau 3 |
scores.len pada Vec |
field `len` of struct `Vec` is private, ditambah help: a method `len` also exists, call it with parentheses (ada method len, panggil dengan tanda kurung) |
Perbaikan 1 |
timeout.secs pada Duration |
field `secs` of struct `Duration` is private |
Perbaikan 1 (as_secs()) |
account.balance = 500 |
E0616 yang sama: menulis juga diblokir | Perbaikan 2 |
Apa artinya
Section titled “Apa artinya”Panahnya menunjuk nama field sesudah titik. account.owner di baris yang sama tidak bermasalah, karena owner ditandai pub. balance tidak, jadi hanya kode di dalam mod bank yang boleh membaca atau mengubahnya.
Perhatikan bahwa Account sendiri sudah pub. Bagian inilah yang mengejutkan banyak orang: membuat struct menjadi publik tidak membuat field-nya ikut publik. Setiap field butuh pub-nya sendiri, atau tetap privat.
Bayangkan sebuah bank. Kamu boleh masuk, dan siapa pun bisa melihat nama pemilik rekeningmu. Tapi kamu tidak bisa masuk ke balik meja lalu membuka brankas untuk menghitung uangnya. Kamu minta tolong ke teller, dan teller mengikuti aturan bank.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Di Rust, semuanya privat secara default: fungsi, modul, dan juga field struct (lihat Modul). Privasi ditentukan oleh modul, bukan oleh tipe. Semua kode di dalam mod bank boleh menyentuh balance, dan kode di luarnya tidak.
Tujuannya supaya sebuah struct bisa menjaga aturannya sendiri. Misalnya saldo bank tidak boleh negatif. Kalau setiap bagian program bisa menulis account.balance = ..., bagian mana pun bisa melanggar aturan itu, dan kamu harus menyisir seluruh kode untuk mencari pelakunya. Kalau field-nya privat, hanya segelintir method di dalam mod bank yang bisa mengubahnya. Periksa aturannya di sana, dan aturan itu berlaku di mana-mana. Ide ini disebut encapsulation (enkapsulasi).
Standard library juga melakukan hal yang sama. Vec punya field privat untuk panjangnya dan buffer memorinya. Kalau kamu bisa menulis v.len = 100 pada vektor yang hanya berisi 3 item, membaca v[50] akan membaca memori acak. Menjaga len tetap privat itulah yang membuat Vec aman dipakai.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Panggil method-nya, bukan membaca field-nya
Section titled “Perbaikan 1: Panggil method-nya, bukan membaca field-nya”Pilih ini kalau struct-nya berasal dari standard library atau crate lain. Kamu tidak bisa mengubah kode mereka, dan mereka selalu menyediakan method untuk hal-hal yang boleh kamu lihat. Kalau rustc bilang help: a method ... also exists, tambahkan ():
use std::time::Duration;
fn main() { let scores = vec![10, 20, 30]; println!("{} skor", scores.len());
let timeout = Duration::from_secs(90); println!("Timeout: {} detik", timeout.as_secs());}Output:
3 skorTimeout: 90 detikNama method-nya tidak selalu sama dengan nama field-nya (secs dibaca dengan as_secs()). Lihat halaman tipe itu di docs.rs, atau biarkan editor-mu menampilkan daftar method setelah kamu mengetik titik.
Perbaikan 2: Tambahkan getter, dan method yang mengikuti aturan
Section titled “Perbaikan 2: Tambahkan getter, dan method yang mengikuti aturan”Pilih ini kalau struct-nya milikmu sendiri dan field-nya punya aturan yang perlu dijaga. Biarkan field-nya privat, tambahkan pub fn yang mengembalikan nilainya (sebuah getter), dan ubah field itu hanya lewat method yang memeriksa aturannya:
mod bank { pub struct Account { pub owner: String, balance: i64, // privat: hanya modul ini yang bisa mengubahnya }
impl Account { pub fn new(owner: &str) -> Account { Account { owner: owner.to_string(), balance: 0 } }
// Getter: siapa saja boleh membaca saldonya. pub fn balance(&self) -> i64 { self.balance }
pub fn deposit(&mut self, amount: i64) { if amount > 0 { self.balance += amount; } }
// Aturannya ada di sini: saldo tidak pernah di bawah nol. pub fn withdraw(&mut self, amount: i64) -> Result<(), String> { if amount > self.balance { return Err(format!("hanya tersedia {}", self.balance)); } self.balance -= amount; Ok(()) } }}
fn main() { let mut account = bank::Account::new("Ferris"); account.deposit(100); println!("Saldo {}: {}", account.owner, account.balance());
match account.withdraw(500) { Ok(()) => println!("Berhasil menarik 500"), Err(e) => println!("Tidak bisa menarik 500: {e}"), } println!("Saldo masih {}", account.balance());}Output:
Saldo Ferris: 100Tidak bisa menarik 500: hanya tersedia 100Saldo masih 100Rust membolehkan method dan field punya nama yang sama, jadi balance() adalah nama yang lazim untuk getter-nya (bukan get_balance()). Begitu getter-nya ada, rustc bahkan menyarankannya: help: a method `balance` also exists, call it with parentheses. deposit dan withdraw adalah setter-mu: keduanya mengubah field, tapi hanya dengan cara yang diizinkan aturan. Selengkapnya tentang method di Struct.
Perbaikan 3: Jadikan field-nya pub kalau datanya sederhana
Section titled “Perbaikan 3: Jadikan field-nya pub kalau datanya sederhana”Pilih ini kalau nilai apa pun boleh dan tidak ada hal lain yang bergantung pada field itu. Sebuah titik di grid, sebuah warna, atau struct pengaturan tidak punya aturan yang perlu dijaga. Getter di situ hanya menambah ketikan:
mod geometry { pub struct Point { pub x: i32, pub y: i32, }}
fn main() { let mut p = geometry::Point { x: 3, y: 4 }; p.x += 1; println!("Titik di ({}, {})", p.x, p.y);}Output:
Titik di (4, 4)Kalau hanya kodemu sendiri yang boleh melihat field itu, tulis pub(crate) x: i32 (semua modul di crate ini) atau pub(super) x: i32 (hanya modul induknya). Di sebuah program, keduanya berperilaku seperti pub; di sebuah library, keduanya menjaga field itu tetap di luar API publikmu. Halaman E0603 punya tabel semua tingkatannya.
Jadi, langsung jadikan pub saja? Tanyakan: “Apakah ada nilai tertentu untuk field ini, atau perubahan pada field ini saja, yang bisa membuat struct-nya salah?” Saldo negatif, len yang tidak cocok dengan datanya, total yang tidak lagi sama dengan jumlah item-nya: biarkan yang seperti itu privat dan pakai Perbaikan 2. Kalau jawabannya “tidak, nilai apa pun boleh”, pub adalah pilihan yang jujur.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”len pada Vec. Kamu menulis scores.len dan mendapat field `len` of struct `Vec` is private. Itu karena Vec memang punya field privat bernama len. Perbaikannya scores.len(). Detail lucunya: name.len pada String memberi error lain, E0615 (attempted to take value of method, mencoba mengambil nilai dari method), karena String tidak punya field dengan nama itu. Perbaikannya sama.
Mengubah field dari luar. account.balance = 500; memberi E0616 yang sama. Menulis juga diblokir. Jangan jadikan field-nya pub hanya supaya bisa diubah; tambahkan method seperti deposit yang melakukan perubahan itu sekaligus memeriksanya.
Setelah memindahkan struct ke modul atau file-nya sendiri. Kode di main.rs sudah berbulan-bulan memakai user.email. Lalu kamu memindahkan User ke src/user.rs, dan semua akses field langsung rusak. Field yang tadinya tidak bermasalah sekarang privat di mod user. Tambahkan pub pada field yang berisi data sederhana, dan getter untuk sisanya.
Test. Blok #[cfg(test)] mod tests di dalam file yang sama adalah modul anak, jadi ia boleh membaca field privat. Test di folder tests/ berada di luar crate-mu dan hanya bisa memakai API pub, sama seperti pengguna lain.
Error terkait
Section titled “Error terkait”- E0603:
function `x` is private. Ide yang sama untuk fungsi, struct, dan modul. - E0451: field privat yang sama, tapi saat membuat struct dengan
Account { ... }. - E0624:
method `x` is private. Method-nya (ataunew) juga butuhpub. - E0609:
no field `x` on type `T`. Field-nya sama sekali tidak ada (sering karena salah ketik). - E0615:
attempted to take value of method. Kamu menulisx.lenpadahal maksudnyax.len(). - Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. pub struct Account { balance: u64 } ada di dalam mod bank. Bisakah main membaca account.balance?
2. Kamu mendapat `field len of struct Vec is private`. Apa perbaikannya?
3. Struct Score punya field points yang harus tetap di antara 0 dan 100. Desain apa yang paling baik?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0616 — Rust error codes index (bahasa Inggris): penjelasan resmi dengan contoh minimal.
- Making Structs and Enums Public — The Rust Book (bahasa Inggris): kenapa
pub structtetap punya field privat, dengan contoh restoran. - Encapsulation that Hides Implementation Details — The Rust Book (bahasa Inggris): struct yang menjaga nilai rata-ratanya tetap benar dengan membiarkan field-nya privat.
- Struct visibility — Rust by Example (bahasa Inggris): field publik dan privat berdampingan, dalam satu contoh yang bisa dijalankan.
- Structs have private fields (C-STRUCT-PRIVATE) — Rust API Guidelines (bahasa Inggris): kenapa library membiarkan field-nya privat supaya bisa mengubahnya nanti.