構造体
struct
キーワードを使うことで、独自の構造を持つ型を定義することができます。一つの型に関連する値を複数持たせることで、管理しやすくなります。
宣言
構造体を宣言するには、struct <構造体名>
の後にフィールド(名前と型のペア)を列挙します。
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
構造体のフィールドに他の構造体を指定することもできます。
struct Address {
city: String,
postal_code: String,
}
struct User {
username: String,
email: String,
address: Address,
}
作成
構造体のインスタンスを作成する場合は、構造体名の後に、名前と値を列挙した{}
を書きます。
let user = User {
username: String::from("Alice"),
email: String::from("alice@example.com"),
sign_in_count: 1,
active: true,
};
構造体のフィールドの値として、そのフィールドの名前と同名の変数を設定する場合、:
を省略することができます。
let username = String::from("Bob");
let email = String::from("bob@example.com");
let user = User {
username,
email,
sign_in_count: 0,
active: false,
};
同じ構造体の別のインスタンスからコピーしつつ、一部のフィールドを変更したい場合は..
を使うことができます。
let user1 = User {
username: String::from("Charlie"),
email: String::from("charlie@example.com"),
sign_in_count: 1,
active: true,
};
let user2 = User {
email: String::from("charlie_new@example.com"),
..user1
};
参照
構造体のフィールドには構造体名.フィールド名
でアクセスできます。
println!("Username: {}", user.username);
println!("Email: {}", user.email);
デストラクト
ある構造体のインスタンスのうち、指定したフィールドを個別に新しい変数として抜き出したい場合はデストラクト構文が使えます。
let User {
username,
email,
sign_in_count,
active,
} = user;
println!("Username: {}", username);
TypeScriptのオブジェクト型にかなり近い使用感なので、とっつきやすいですね。TypeScriptでいう分割代入やspread演算子(...
)相当のものが用意されているのも親しみがわきます。
構造体のインスタンスを関数に渡すときなどは、インスタンスへの参照が渡されます。
タプル構造体
構造体には他にも種類があり、フィールド名を持たず型の組み合わせだけを持つ「タプル構造体」というものがあります。基本的に、構造体はいくつかの値をまとめて整理するために定義しますが、その際に名前を付ける必要がない(冗長である)場合に使用します。
struct Color(u8, u8, u8);
let black = Color(0, 0, 0);
println!("Red: {}, Green: {}, Blue: {}", black.0, black.1, black.2);
ユニット構造体
中身がない構造体を「ユニット構造体」と呼びます。中身がないため値は持ちませんが、後日紹介するトレイトを実装することで、値はないが関数はある構造体を表現できます。
struct Unit;
impl Unit {
fn do_something() {
println!("Unit struct method called");
}
}
Unit::do_something();
ユニット構造体の出番がよくわかっていません。いくつかの関数をユーティリティとしてまとめたいときに使うんでしょうか。