Structs
Versi Bahasa Indonesia. Baca dalam Bahasa Inggris
- Struct:
- Struct adalah tipe yang ditentukan pengguna (user-defined) yang memungkinkan kamu mengelompokkan data terkait bersama-sama mirip dengan tuple.
- Tidak seperti tuple, dalam struct kamu akan memberi nama setiap bagian data sehingga jelas apa arti nilai-nilai tersebut.
- Menambahkan nama-nama ini berarti struct lebih fleksibel daripada tuple sehingga kamu tidak harus bergantung pada urutan data untuk menentukan atau mengakses nilai dari sebuah instance.
- Struct dapat memiliki associated methods, yaitu fungsi yang terikat pada struct.
- Memiliki kemampuan struct update syntax menggunakan
... - Tipe struct di Rust adalah:
- Regular Struct: Field diberi nama secara eksplisit.
- Tuple Struct: Field diidentifikasi berdasarkan posisinya (seperti tuple).
- Unit-Like Struct: Struct tanpa field.
- Method:
- Method mirip dengan fungsi: kita mendeklarasikannya dengan keyword fn dan sebuah nama.
- Tidak seperti fungsi, method didefinisikan dalam konteks sebuah struct (atau enum atau trait object).
- Parameter pertamanya selalu self, yang mewakili instance dari struct tempat method dipanggil.
- Referensi:
structs1.rs
struct ColorRegularStruct {
// Add the fields that the test `regular_structs` expects.
// What types should the fields have? What are the minimum and maximum values for RGB colors?
red: i32,
green: i32,
blue: i32,
}
struct ColorTupleStruct(i32, i32, i32);
#[derive(Debug)]
struct UnitStruct;
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn regular_structs() {
// Instantiate a regular struct.
let green = ColorRegularStruct {
red: 0,
green: 255,
blue: 0,
};
assert_eq!(green.red, 0);
assert_eq!(green.green, 255);
assert_eq!(green.blue, 0);
}
#[test]
fn tuple_structs() {
// Instantiate a tuple struct.
let green = ColorTupleStruct(0, 255, 0);
assert_eq!(green.0, 0);
assert_eq!(green.1, 255);
assert_eq!(green.2, 0);
}
#[test]
fn unit_structs() {
// Instantiate a unit struct.
let unit_struct = UnitStruct;
let message = format!("{unit_struct:?}s are fun!");
assert_eq!(message, "UnitStructs are fun!");
}
}- Di latihan ini kita akan mendefinisikan 3 tipe struct.
- Pertama adalah regular struct.
-
Berdasarkan test, ia mengharapkan 3 field
red,green, danbluejadi kita dapat mendefinisikannya seperti ini:struct ColorRegularStruct { red: i32, green: i32, blue: i32, } // dan menggunakannya seperti ini let green = ColorRegularStruct { red: 0, green: 255, blue: 0, };
-
- Kedua adalah tuple struct.
-
Berdasarkan test, ia juga mengharapkan 3 field, jadi kita mendefinisikannya seperti ini:
struct ColorTupleStruct(i32, i32, i32); // dan menggunakannya seperti ini let green = ColorTupleStruct(0, 255, 0);
-
- Dan terakhir adalah unit-like struct.
-
Sudah didefinisikan dan kita hanya perlu menginstansiasikannya seperti ini:
let unit_struct = UnitStruct;
-
structs2.rs
#[derive(Debug)]
struct Order {
name: String,
year: u32,
made_by_phone: bool,
made_by_mobile: bool,
made_by_email: bool,
item_number: u32,
count: u32,
}
fn create_order_template() -> Order {
Order {
name: String::from("Bob"),
year: 2019,
made_by_phone: false,
made_by_mobile: false,
made_by_email: true,
item_number: 123,
count: 0,
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn your_order() {
let order_template = create_order_template();
// Create your own order using the update syntax and template above!
let your_order = Order {
name: String::from("Hacker in Rust"),
count: 1,
..order_template
};
assert_eq!(your_order.name, "Hacker in Rust");
assert_eq!(your_order.year, order_template.year);
assert_eq!(your_order.made_by_phone, order_template.made_by_phone);
assert_eq!(your_order.made_by_mobile, order_template.made_by_mobile);
assert_eq!(your_order.made_by_email, order_template.made_by_email);
assert_eq!(your_order.item_number, order_template.item_number);
assert_eq!(your_order.count, 1);
}
}-
Di latihan ini kita perlu membuat
Orderdariorder_templatedengan menggunakan struct update syntax. -
Jadi berdasarkan test kita hanya perlu mengubah
namedancountmaka kita melakukannya seperti ini:let your_order = Order { name: String::from("Hacker in Rust"), count: 1, ..order_template }; -
Kamu dapat membaca lebih lanjut di sini: Creating Instances from Other Instances with Struct Update Syntax.
structs3.rs
// Structs contain data, but can also have logic. In this exercise, we have
// defined the `Package` struct, and we want to test some logic attached to it.
#[derive(Debug)]
struct Package {
sender_country: String,
recipient_country: String,
weight_in_grams: u32,
}
impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self {
if weight_in_grams < 10 {
// This isn't how you should handle errors in Rust, but we will
// learn about error handling later.
panic!("Can't ship a package with weight below 10 grams");
}
Self {
sender_country,
recipient_country,
weight_in_grams,
}
}
// Add the correct return type to the function signature.
fn is_international(&self) -> bool {
self.sender_country != self.recipient_country
}
// Add the correct return type to the function signature.
fn get_fees(&self, cents_per_gram: u32) -> u32 {
self.weight_in_grams * cents_per_gram
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn fail_creating_weightless_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Austria");
Package::new(sender_country, recipient_country, 5);
}
#[test]
fn create_international_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Russia");
let package = Package::new(sender_country, recipient_country, 1200);
assert!(package.is_international());
}
#[test]
fn create_local_package() {
let sender_country = String::from("Canada");
let recipient_country = sender_country.clone();
let package = Package::new(sender_country, recipient_country, 1200);
assert!(!package.is_international());
}
#[test]
fn calculate_transport_fees() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Spain");
let cents_per_gram = 3;
let package = Package::new(sender_country, recipient_country, 1500);
assert_eq!(package.get_fees(cents_per_gram), 4500);
assert_eq!(package.get_fees(cents_per_gram * 2), 9000);
}
}-
Di latihan ini kita perlu memperbaiki dua method.
-
Pertama adalah
is_international, berdasarkan test jikasender_countrydanrecipient_countryberbeda maka dianggap internasional, dan tipe kembalian yang diharapkan adalahbool.fn is_international(&self) -> bool { self.sender_country != self.recipient_country } -
Kedua adalah
get_fees, berdasarkan test rumus biayanya adalahweight_in_grams * cents_per_gramdan tipe kembalian yang diharapkan adalahu32.fn get_fees(&self, cents_per_gram: u32) -> u32 { self.weight_in_grams * cents_per_gram }
Last updated on