Lewati ke konten

Error Rust E0624: method is private (method privat)

E0624 artinya: method yang kamu panggil memang ada, tapi ditulis tanpa pub, jadi hanya kode di dalam modulnya yang boleh memanggilnya. Struct-nya boleh publik, modulnya juga. Method tetap mulai sebagai privat, satu per satu. Error ini sangat sering muncul tepat setelah kamu memindahkan sebuah tipe ke modulnya sendiri, dan perbaikannya biasanya menambahkan pub di depan fn. Halaman ini bagian dari Penjelasan error compiler Rust.

error[E0624]: associated function `new` is private
--> src/main.rs:18:38
|
7 | fn new() -> Account { // no `pub`
| ------------------- private associated function defined here
...
18 | let mut account = bank::Account::new(); // ❌ private associated function
| ^^^ private associated function
error[E0624]: method `add_interest` is private
--> src/main.rs:19:13
|
11 | fn add_interest(&mut self) { // no `pub`
| -------------------------- private method defined here
...
19 | account.add_interest(); // ❌ private method
| ^^^^^^^^^^^^ private method

Compiler melaporkan dua error: associated function new privat, dan method add_interest juga privat. Masing-masing menunjukkan tempat fungsi itu didefinisikan (defined here).

Ini program yang menghasilkan error tersebut:

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
fn new() -> Account { // no `pub`
Account { balance: 0 }
}
fn add_interest(&mut self) { // no `pub`
self.balance += self.balance / 100;
}
}
}
fn main() {
let mut account = bank::Account::new(); // ❌ private associated function
account.add_interest(); // ❌ private method
}

rustc memakai dua nama di sini. Method menerima self (account.add_interest()). Associated function tidak punya self dan dipanggil dengan :: (Account::new()). Aturan dan perbaikannya sama untuk keduanya.

Setiap error punya dua panah. Panah ^^^ adalah pemanggilanmu. Panah --- menunjukkan baris fn yang tidak punya pub. Jadi pesannya memberi tahu persis di mana kamu harus menambahkannya.

Berada di dalam impl Account tidak membuat sebuah method menjadi publik, bahkan kalau Account sudah pub. Bayangkan sebuah restoran: menunya publik, jadi kamu bisa memesan hidangan (method pub). Dapur punya langkah-langkahnya sendiri, seperti “iris bawang”, yang tidak bisa kamu minta secara langsung. Itulah method privat.

Semua yang ada di Rust privat secara default, dan method tidak terkecuali (lihat Modul). Privasi dimiliki oleh modul tempat blok impl ditulis: kode apa pun di mod bank boleh memanggil add_interest, dan kode di luarnya tidak.

Ini membuat sebuah tipe bisa menyimpan method pembantu kecil yang hanya masuk akal kalau dijalankan dengan urutan yang benar. Misalnya add_interest hanya boleh berjalan sebulan sekali, setelah biaya administrasi dipotong. Kalau siapa saja bisa memanggilnya, suatu saat seseorang akan memanggilnya dua kali tanpa sengaja. Method pembantu yang privat ditambah satu method publik yang menjalankannya dengan benar membuat kesalahan itu mustahil terjadi.

Ini juga membuat pilihanmu tetap terbuka. Method privat bisa diganti namanya, digabung, atau dihapus kapan saja, karena compiler menjamin tidak ada kode di luar yang memakainya.

Perbaikan 1: Tambahkan pub pada method-nya

Section titled “Perbaikan 1: Tambahkan pub pada method-nya”

Pilih ini kalau method-nya memang dimaksudkan untuk dipanggil dari luar. Untuk new, hampir selalu begitu: constructor yang tidak bisa dipanggil siapa pun tidak banyak gunanya.

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
pub fn add_interest(&mut self) {
self.balance += self.balance / 100; // 1%
}
pub fn balance(&self) -> u64 {
self.balance
}
}
}
fn main() {
let mut account = bank::Account::new(1000);
account.add_interest();
println!("Saldo: {}", account.balance());
}

Output:

Saldo: 1010
▶ Coba sendiri

Perbaikan 2: Panggil method publik yang memang disediakan untukmu

Section titled “Perbaikan 2: Panggil method publik yang memang disediakan untukmu”

Pilih ini kalau method privatnya adalah pembantu, terutama di kode yang bukan kamu tulis. Sering ada method publik yang memanggilnya untukmu, dengan urutan yang benar dan pemeriksaan yang tepat. Di sini, membiarkan add_interest tetap privat adalah desain yang benar:

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
// Pintu masuk publik: satu panggilan mengerjakan seluruh bulan, dengan urutan yang benar.
pub fn close_month(&mut self) {
self.charge_fee();
self.add_interest();
}
pub fn balance(&self) -> u64 {
self.balance
}
// Pembantu privat: memanggilnya sendirian, atau dua kali, memberi hasil yang salah.
fn charge_fee(&mut self) {
self.balance = self.balance.saturating_sub(5);
}
fn add_interest(&mut self) {
self.balance += self.balance / 100;
}
}
}
fn main() {
let mut account = bank::Account::new(1000);
account.close_month();
println!("Setelah satu bulan: {}", account.balance());
// account.add_interest(); // ❌ E0624: method `add_interest` is private
}

Output:

Setelah satu bulan: 1004
▶ Coba sendiri

Aturan yang bagus: jadikan sebuah method pub hanya kalau memanggilnya sendirian, kapan saja tidak bisa merusak struct-nya. Kalau method itu hanya masuk akal sebagai satu langkah dari sesuatu yang lebih besar, biarkan privat dan sediakan yang lebih besar itu.

Perbaikan 3: Pakai pub(crate) untuk “hanya kodeku”

Section titled “Perbaikan 3: Pakai pub(crate) untuk “hanya kodeku””

Pilih ini kalau modul lain di crate-mu butuh method itu, tapi orang yang memakai library-mu tidak boleh. pub(super) (hanya modul induknya) bekerja dengan cara yang sama; halaman E0603 punya tabel semua tingkatannya.

mod shop {
pub struct Cart {
prices: Vec<u32>,
}
impl Cart {
pub fn new() -> Cart {
Cart { prices: Vec::new() }
}
pub fn add(&mut self, price: u32) {
self.prices.push(price);
}
// Hanya untuk kode kita sendiri (seperti struk), bukan untuk pengguna library.
pub(crate) fn total(&self) -> u32 {
self.prices.iter().sum()
}
}
}
mod receipt {
pub fn print(cart: &crate::shop::Cart) {
println!("Total: {}", cart.total());
}
}
fn main() {
let mut cart = shop::Cart::new();
cart.add(3);
cart.add(5);
receipt::print(&cart);
}

Output:

Total: 8
▶ Coba sendiri

Satu hal yang perlu diwaspadai: di package yang punya src/lib.rs sekaligus src/main.rs, keduanya adalah dua crate. pub(crate) fn total di lib.rs itu privat bagi main.rs:

error[E0624]: method `total` is private
--> src/main.rs:3:25
|
3 | println!("{}", cart.total());
| ^^^^^ private method
|
::: src/lib.rs:10:5
|
10 | pub(crate) fn total(&self) -> u32 {
| --------------------------------- private method defined here

Compiler bilang method total privat. Baris ::: src/lib.rs menunjukkan bahwa method itu didefinisikan di crate lain, yaitu library-nya.

Di situ, pakai pub biasa. Lihat Cargo dan crate.

Perbaikan 4: Pindahkan kode yang membutuhkannya ke dalam modul

Section titled “Perbaikan 4: Pindahkan kode yang membutuhkannya ke dalam modul”

Pilih ini kalau method-nya memang harus tetap privat, tapi ada kode yang tetap membutuhkannya, seperti pemeriksaan audit atau test. Kode di modul yang sama boleh memanggilnya, begitu juga modul anak: modul di dalam bank bisa melihat semua yang privat di bank.

mod bank {
pub struct Account {
balance: u64,
}
impl Account {
pub fn new(opening: u64) -> Account {
Account { balance: opening }
}
fn is_suspicious(&self) -> bool {
self.balance > 10_000
}
}
// Modul anak boleh memakai semua yang privat di modul induknya.
pub mod audit {
pub fn check(account: &super::Account) -> &'static str {
if account.is_suspicious() { "perlu diperiksa" } else { "aman" }
}
}
}
fn main() {
let small = bank::Account::new(500);
let big = bank::Account::new(50_000);
println!("kecil: {}", bank::audit::check(&small));
println!("besar: {}", bank::audit::check(&big));
}

Output:

kecil: aman
besar: perlu diperiksa
▶ Coba sendiri

Unit test bekerja dengan cara yang sama. mod tests yang ditulis di dalam bank (atau di bagian bawah src/bank.rs) adalah modul anak, jadi ia boleh memanggil method privat. Lihat Testing:

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn not_suspicious_when_small() {
let account = Account::new(500);
assert!(!account.is_suspicious()); // privat, tapi boleh di sini
}
}

Blok impl di modul yang berbeda. Privasi dimiliki oleh modul tempat impl ditulis, bukan oleh struct-nya. Kalau Order tinggal di mod model tapi kamu menulis impl Order { fn with_tax(&self) ... } di dalam mod pricing, maka main mendapat method `with_tax` is private, yang menunjuk ke mod pricing. Perbaikannya: pub fn with_tax, atau pub(crate).

Memakai method sebagai nilai fungsi. accounts.iter().map(bank::Account::audit) adalah pemanggilan yang sama dengan penulisan berbeda, jadi memberi E0624 yang sama. Perbaikannya pun sama.

Method trait. Kamu tidak pernah menulis pub pada method di dalam impl SomeTrait for Type. Method itu sepublik trait-nya, dan menambahkan pub justru error: error[E0449]: visibility qualifiers are not permitted here (penanda visibilitas tidak diizinkan di sini). Kalau sebuah method trait seolah hilang, kamu akan mendapat E0599, dan perbaikannya adalah use trait-nya.

Method privat milik sebuah crate. Kamu menemukan method yang pas di source code sebuah crate di GitHub, tapi method itu tidak pub. Kamu tidak bisa memanggilnya, dan pembuatnya bisa mengubahnya di rilis mana pun. Cari method publik yang melakukan hal yang sama di halaman crate itu di docs.rs; hanya item pub yang tampil di sana.

  • E0603: function `x` is private. Ide yang sama untuk fungsi biasa, struct, dan modul.
  • E0616: field `x` of struct `Y` is private, saat membaca atau mengubah sebuah field.
  • E0451: field privat saat membuat struct dengan Y { ... }. Biasanya diperbaiki dengan pub fn new.
  • E0599: no method named `x` found. Method itu tidak ada untuk tipe tersebut, atau trait-nya belum masuk scope.
  • Semua error compiler: daftar lengkap halaman error.

Kuis singkat

1. pub struct Timer punya impl Timer { fn start() -> Timer { ... } } di dalam mod clock. Apa yang terjadi saat main memanggil clock::Timer::start()?

2. Kode mana yang boleh memanggil method privat yang didefinisikan di mod bank?

3. add_interest yang privat hanya boleh berjalan sebulan sekali, setelah biaya dipotong. Apa perbaikan terbaik untuk E0624?

Skor: 0 / 3