Modul di Rust
Sejauh ini, semua contoh ditulis di satu file main.rs. Untuk program kecil itu tidak masalah, tapi proyek sungguhan memecah kode menjadi bagian-bagian yang logis. Alat yang Rust sediakan untuk itu adalah sistem modul: mod, pub, dan use.
Mendefinisikan modul
Section titled “Mendefinisikan modul”Modul adalah blok bernama yang mengelompokkan kode yang saling berhubungan:
mod math { pub fn add(a: i32, b: i32) -> i32 { a + b }}
fn main() { let sum = math::add(2, 3); println!("{sum}");}Output:
5Ada dua hal yang perlu diperhatikan. Pertama, fungsinya dipanggil dengan math::add(...), yaitu memakai nama modul sebagai path. Kedua, fungsi itu ditandai pub. Tanpa pub, fungsi tersebut tidak bisa dipanggil dari luar modul.
Semuanya private secara default
Section titled “Semuanya private secara default”Bagian ini perlu ditekankan karena sering bikin kaget: isi modul bersifat private secara default. Kalau kamu menghapus pub dari contoh di atas, kodenya tidak akan bisa di-compile:
mod math { fn add(a: i32, b: i32) -> i32 { // tanpa `pub` a + b }}
fn main() { let sum = math::add(2, 3); // ❌ error: function `add` is private println!("{sum}");}Pesan error dari compiler tetap dalam bahasa Inggris: “function add is private” artinya fungsi add bersifat private.
Apa pun yang ingin kamu pakai dari luar modul harus kamu tandai sendiri dengan pub. Ini memang disengaja: dengan begitu, modul bisa menyembunyikan fungsi-fungsi pembantu internalnya dan hanya membuka bagian yang memang dimaksudkan sebagai API publik.
Modul bersarang
Section titled “Modul bersarang”Modul bisa berisi modul lain. Dengan cara inilah proyek yang lebih besar membangun struktur berbentuk pohon:
mod shapes { pub mod circle { pub fn area(radius: f64) -> f64 { 3.14159 * radius * radius } }}
fn main() { let area = shapes::circle::area(2.0); println!("{area}");}use: menyingkat path yang panjang
Section titled “use: menyingkat path yang panjang”Menulis shapes::circle::area(...) setiap kali lama-lama melelahkan. use membawa sebuah path ke dalam cakupan (scope), sehingga kamu bisa merujuknya secara langsung:
mod shapes { pub mod circle { pub fn area(radius: f64) -> f64 { 3.14159 * radius * radius } }}
use shapes::circle;
fn main() { let area = circle::area(2.0); // lebih pendek daripada shapes::circle::area println!("{area}");}Sebenarnya kamu sudah pernah memakai use. Ini keyword yang sama dengan yang ada di halaman HashMap (use std::collections::HashMap;).
Memecah modul ke beberapa file
Section titled “Memecah modul ke beberapa file”Contoh-contoh di atas menaruh semuanya di satu file, karena Rust Playground memang mengharuskan begitu. Di proyek sungguhan di komputermu sendiri, biasanya setiap modul punya file sendiri. Kalau proyekmu punya modul math, strukturnya biasanya seperti ini:
src/├── main.rs└── math.rsmod math; // memberi tahu Rust: cari kode modul ini di math.rs
fn main() { let sum = math::add(2, 3); println!("{sum}");}pub fn add(a: i32, b: i32) -> i32 { a + b}mod math; (dengan titik koma, tanpa isi) menyuruh Rust memuat isi modul dari file math.rs di folder yang sama. Pola inilah yang akan kamu pakai begitu proyekmu tumbuh lebih dari satu file.
Latihan
Section titled “Latihan”1. Modul konversi suhu
Section titled “1. Modul konversi suhu”Buat modul bernama convert dengan dua fungsi publik: c_to_f (Celsius ke Fahrenheit) dan f_to_c (kebalikannya). Dari main, cetak 100°C sama dengan 212°F dan 212°F sama dengan 100°C.
Petunjuk: rumusnya c * 9.0 / 5.0 + 32.0 dan (f - 32.0) * 5.0 / 9.0. Jangan lupa pub, dan panggil fungsinya dengan nama modul, misalnya convert::c_to_f(100.0).
Lihat solusi
mod convert { pub fn c_to_f(c: f64) -> f64 { c * 9.0 / 5.0 + 32.0 }
pub fn f_to_c(f: f64) -> f64 { (f - 32.0) * 5.0 / 9.0 }}
fn main() { println!("100°C sama dengan {}°F", convert::c_to_f(100.0)); println!("212°F sama dengan {}°C", convert::f_to_c(212.0));}Output:
100°C sama dengan 212°F212°F sama dengan 100°CKedua fungsi ditandai pub, jadi main (yang berada di luar modul) bisa memanggilnya. Hapus salah satu pub, dan compiler akan memberi tahu bahwa fungsi itu private.
2. Fungsi pembantu yang private
Section titled “2. Fungsi pembantu yang private”Buat modul bersarang school::grades dengan fungsi publik letter(score: u32) -> char yang mengembalikan 'A' untuk nilai 90 ke atas, 'B' untuk 80 ke atas, dan 'C' untuk sisanya. Di dalam grades, tulis juga fungsi pembantu private is_at_least(score: u32, min: u32) -> bool yang dipakai oleh letter. Bawa school::grades ke dalam cakupan dengan use, lalu cetak huruf nilai untuk 95, 85, dan 70.
Petunjuk: mod grades di dalam school dan fn letter sama-sama butuh pub, tapi is_at_least jangan diberi pub. Kode di dalam modul yang sama selalu bisa memanggil fungsi private.
Lihat solusi
mod school { pub mod grades { pub fn letter(score: u32) -> char { if is_at_least(score, 90) { 'A' } else if is_at_least(score, 80) { 'B' } else { 'C' } }
// private: hanya kode di dalam `grades` yang bisa memanggilnya fn is_at_least(score: u32, min: u32) -> bool { score >= min } }}
use school::grades;
fn main() { for score in [95, 85, 70] { println!("{score} -> {}", grades::letter(score)); }}Output:
95 -> A85 -> B70 -> Cletter bisa memanggil is_at_least karena keduanya berada di modul yang sama. Dari main, grades::is_at_least(95, 90) akan gagal dengan error “function is_at_least is private”. Justru itulah tujuannya: modul hanya menampilkan API publik yang kecil dan menyimpan fungsi pembantunya untuk dirinya sendiri.
Ringkasan
Section titled “Ringkasan”mod nama { ... }mengelompokkan kode yang berhubungan ke dalam sebuah modul bernama.- Semua yang ada di dalam modul bersifat private secara default. Tambahkan
pubsupaya bisa dipakai dari luar modul. usemembawa sebuah path ke dalam cakupan, jadi kamu tidak perlu menulisnya lengkap setiap kali.- Di proyek dengan banyak file,
mod nama;(tanpa isi) memuat kode modul itu dari file dengan nama yang sama. - Kode di dalam modul selalu bisa memakai item private milik modul itu, jadi biarkan fungsi pembantu tetap private dan buka hanya yang dibutuhkan pemanggil.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. Secara default, apakah item di dalam mod bersifat public atau private?
2. Bagaimana cara menyuruh Rust memuat kode modul dari math.rs, alih-alih menulisnya langsung di tempat?
Skor: 0 / 2
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- Managing Growing Projects with Packages, Crates, and Modules — The Rust Book (bahasa Inggris): bab resmi tentang package, crate, dan modul, serta bagaimana semuanya saling terhubung.
- Defining Modules to Control Scope and Privacy — The Rust Book (bahasa Inggris): contoh lengkap sebuah pohon modul, dengan ringkasan aturan yang praktis.
- Separating Modules into Different Files — The Rust Book (bahasa Inggris): susunan proyek multi-file secara lebih detail, termasuk folder untuk modul bersarang.
- Modules — Rust by Example (bahasa Inggris): contoh yang bisa dijalankan tentang visibilitas,
use,super, danself. - Visibility and privacy — The Rust Reference (bahasa Inggris): aturan lengkapnya, termasuk
pub(crate)untuk “public, tapi hanya di dalam crate saya”.