構造体
理解
基本構文
// 类型声明 struct User { active: bool, username: String, email: String, sign_in_count: u64, } // 实例化 let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; // 访问&修改 let mut user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; user1.email = String::from("anotheremail@example.com"); // field init shorthand fn build_user(email: String, username: String) -> User { User { email, username, active: true, sign_in_count: 1, } } // struct update let user2 = User { email: String::from("another@example.com"), ..user1 } // 这里 user1 move 了,因为 user1.username (String 类型) 被 move 为 user2.username // 如果初始化 user2 的时候另外赋值 username,则 user1 不会被 moveメソッド
struct の impl の function は method または associated function と呼びます。method と field は同名にできます
複数の impl を同時に定義できます
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { // method self.width * self.height } fn width(&self) -> bool { // method 与 field 可以同名 self.width > 0 } fn square(size: u32) -> Rectangle { // 不带 &self 也可以 Rectangle { width: size, height: size, } } } // 可同时存在多个 impl impl Rectangle { fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height } } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!( "The area of the rectangle is {} square pixels.", rect1.area() ); if rect1.width() { println!("The rectangle has a nonzero width; it is {}", rect1.width); } }
参照元
…
Creating Instances From Other Instances With Struct Update Syntax
古いインスタンスの値の大部分を使いながら一部を変した新しい struct インスタンスを作ると便利なことがあります。struct update syntax を使えば実現できます。
まず、リスト 5-6 では update syntax を使わず、user1 から user2 に新しい User インスタンスを作ります。email だけ新しい値にし、それ以はリスト 5-2 で作った user1 と同じ値を使います。
let user2 = User {
active: user1.active,
username: user1.username,
email: String::from("another@example.com"),
sign_in_count: user1.sign_in_count,
};
リスト 5-6: user1 の値を使った新しい User インスタンスの作成
struct update syntax を使えば、リスト 5-7 のように、より少ないコードで同じ結果を得られます。.. は、明示的に設定していない残りのフィールドに、指定したインスタンスと同じ値を使うことを示します。
let user2 = User {
email: String::from("another@example.com"),
..user1
};
リスト 5-7: struct update syntax で User の新しい email 値を設定し、残りの値に user1 を使う
リスト 5-7 のコードは、email だけ異なり、username、active、sign_in_count は user1 と同じ値を持つ user2 を作ります。残りのフィールドを user1 から取得するため、..user1 は最後に置く必要があります。ただし、それ以のフィールドは struct 定義の順序に関係なく、任意の順序で好きな数だけ指定できます。
struct update syntax はデータを move するため、= による代入に似ています。これは
「変数とデータの相互作: Move」
で見たとおりです。この例では、user1 の username フィールドの String が user2 に move されるため、user2 作成後に user1 は使えません。email と username の両方に新しい String 値を user2 へ渡し、user1 から active と sign_in_count だけを使えば、user2 作成後も user1 は有効です。active と sign_in_count は Copy trait を実装する型なので、
「スタックだけに保存されるデータ: Copy」
で説明した動作になります。