Module yang teratur menjaga internal tetap rapi, tetapi kadang struktur internal yang rapi justru memaksa pemakai crate menelusuri jalur yang panjang dan teknis. Restoran kita mungkin menyusun area depan menjadi front_of_house::hosting, sedangkan pelanggan yang memesan hanya ingin tahu satu kata: hosting. Rust menyediakan teknik khusus untuk menjembatani keduanya — re-export lewat pub use — yang menempatkan item module dalam ke jalur publik yang baru. Chapter ini membahas mekanisme re-export, bedahnya dari sisi pemakai crate, dan prinsip desain antarmuka yang menjadikan teknik ini tulang punggung library-library besar.
Masalah: Struktur Internal yang Bocor ke Antarmuka #
Kita mulai dari masalah nyatanya. Crate restoran kita mengelompokkan fungsi pendaftaran pelanggan di module front_of_house::hosting karena struktur tree-nya memang begitu — area depan memiliki sub-bagian hosting. Setiap pengguna crate kini harus menulis:
use resto::front_of_house::hosting::add_to_waitlist;Jalur ini menimbulkan dua kerugian. Pertama, pemakai dipaksa memahami peta internal restoran — padahal front_of_house adalah keputusan organisasi kita, bukan pengetahuan yang bernilai bagi pelanggan. Kedua, antarmuka kita terkunci pada struktur internal: begitu kelak kita menata ulang hosting ke module lain, seluruh kode pemakai yang mengimpor jalur panjang itu patah serentak. Struktur internal yang sehat justru seharusnya bebas berubah tanpa mengguncang pengguna.
pub use: Menempatkan Nama di Jalur Baru #
Pernyataan pub use bekerja seperti use biasa — membawa item ke scope tempat pernyataan itu ditulis — dengan satu kunci tambahan: nama yang dibawa ikut ditandai publik. Efeknya, item yang semula hanya terjangkau lewat jalur dalam kini juga terjangkau lewat jalur pendek dari module tempat pub use ditulis. Kompilator mendaftarkan dua jalur sah menuju item yang sama pada tree; keduanya menunjuk implementasi yang identik, dan tidak ada kode yang digandakan. Kita terapkan pada crate root:
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {
println!("Pelanggan masuk daftar tunggu");
}
}
}
pub use crate::front_of_house::hosting;
fn main() {
hosting::add_to_waitlist();
crate::hosting::add_to_waitlist();
}Output yang Dihasilkan:
Pelanggan masuk daftar tunggu
Pelanggan masuk daftar tungguMari kita bedah kode di atas:
- Baris 1 (
mod front_of_house {): modulefront_of_housesengaja dibiarkan privat. Struktur internal ini bukan urusan pemakai crate — dan justru karena privat, kita bebas menatanya ulang kapan pun. - Baris 9 (
pub use crate::front_of_house::hosting;): pernyataan re-export. Namahostingkini hadir di crate root sebagai nama publik, meskipun module aslinya hidup tersembunyi di dalamfront_of_house. - Baris 12 (
hosting::add_to_waitlist();): pemanggilan lewat nama re-export — bentuk pendek yang ingin kita tawarkan ke seluruh pemakai. - Baris 13 (
crate::hosting::add_to_waitlist();): jalur absolut barucrate::hostingkini sah. Pemakai eksternal nanti cukup menulisuse resto::hosting;— satu kata, tanpa perlu tahu katafront_of_housepernah ada.
Perhatikan hasil akhirnya: module internal tetap privat dan bebas direstrukturisasi, sementara antarmuka publik crate memperlihatkan nama-nama yang kita pilih secara sadar. Pada crate sungguhan sebagai library, pernyataan pub use semacam ini biasanya dituliskan di crate root (src/lib.rs), tepat di tempat pemakai pertama kali mendarat.
Re-export Banyak Item Sekaligus #
Antarmuka nyata jarang cukup satu nama. Kurung kurawal yang kita kenal dari use biasa bekerja penuh pada pub use: beberapa item se-induk digabung dalam satu pernyataan, dan nama fungsi boleh diangkat langsung tanpa membawa module pembungkusnya. Layanan warung kita menyiapkan dua pintu: antrian sebagai module re-export, dan pesan_meja sebagai fungsi yang diangkat langsung:
mod layanan {
pub mod antrian {
pub fn daftar_tunggu() {
println!("Antrian hari ini: Budi, Siti, Citra");
}
}
pub mod meja {
pub fn pesan_meja(nomor: u8) {
println!("Meja nomor {} berhasil dipesan", nomor);
}
}
}
pub use crate::layanan::antrian;
pub use crate::layanan::meja::pesan_meja;
fn main() {
antrian::daftar_tunggu();
pesan_meja(7);
}Output yang Dihasilkan:
Antrian hari ini: Budi, Siti, Citra
Meja nomor 7 berhasil dipesanBedah kode di atas:
- Baris 15 (
pub use crate::layanan::antrian;): moduleantriandi-re-export utuh. Pemakai luar dapat menulisresto::antrian::daftar_tunggu()tanpa menyebutlayanan. - Baris 16 (
pub use crate::layanan::meja::pesan_meja;): fungsipesan_mejadiangkat langsung ke jalur publik crate root. Antarmuka menawarkanresto::pesan_meja(7)— cukup pendek untuk fungsi yang jelas konteksnya, tanpa perlu membawa seluruh modulemeja. - Baris 19 dan Baris 20: dua gaya pemanggilan hasil re-export berdampingan — module ber-prefix dan fungsi langsung. Keduanya sah; pilihan antara keduanya mengikuti keterbacaan di sisi pemakai.
Pola dua tingkat ini lazim di standard library: std::io::prelude dan module prelude crate populer pada umumnya hanyalah kumpulan pub use yang mengemas nama-nama paling sering ke satu jalur pendek.
Re-export juga berperan ketika crate menampung banyak fitur yang perlu diringkas. Sebuah crate domain pembayaran mungkin menyimpan ratusan tipe di module internal gateway, token, dan error, lalu memilih menampilkan belasan nama terpenting di crate root — pemakai cukup menghafal satu tingkat jalur, dan dokumentasi yang dihasilkan cargo doc menampilkan re-export tersebut pada bagian khusus di halaman depan crate. Ketika internal ditata ulang, satu berkas pub use di crate root menjadi satu-satunya tempat yang perlu disesuaikan.
pub use versus use #
Perbedaan keduanya perlu dipatri karena membingungkan pemula persis di momen merancang crate: use adalah urusan pribadi sebuah scope, pub use adalah urusan antarmuka crate. Tabel ringkas berikut merangkum batasnya:
| Aspek | use | pub use |
|---|---|---|
| Tujuan | Singkat menulis path panjang | Merancang jalur publik antarmuka |
| Nama yang dibawa | Hanya terlihat di scope itu | Terlihat dari luar module/crate |
| Memengaruhi pemakai crate | Tidak | Ya — pemakai dapat mengimpor jalur baru |
| Mengubah visibility item asal | Tidak | Tidak — hanya menciptakan jalur tambahan |
Satu baris terakhir tabel sering disalahpahami: pub use tidak mengubah status item di module asalnya. Jika item itu pub, pub use hanya menambahkan pintu kedua; jika kelak internal berubah, kita memindahkan pub use ke sasaran baru dan pemakai tidak perlu tahu.
Ringkasan #
pub use mengangkat item module dalam ke jalur publik baru: nama yang dibawa menjadi bagian antarmuka crate, pemakai cukup mengimpor jalur pendek, dan struktur internal bebas privat serta bebas direstrukturisasi. Kombinasi dengan kurung kurawal memungkinkan pengemasan banyak item sekaligus, dan pola prelude pada standard library adalah contoh matangnya. Seluruh contoh kita sejauh ini masih menulis module di satu berkas — padahal crate nyata memecah kode ke banyak file. Chapter berikutnya memindahkan module-module itu ke berkas masing-masing dengan anotasi mod tanpa isi.