Rustの構造体
名前付き構造体、タプル構造体、ユニット構造体を用いたカスタムデータ型の定義と、implブロックによるメソッド実装を解説します。
Rust基礎シリーズの第7回です。構造体(Struct)を使用すると、関連する複数の値を1つのカスタムデータ型にまとめ、プログラム内の概念をモデリングできます。
構造体の定義とインスタンス化#
一般的な構造体は、名前付きフィールドを持ちます。
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
fn main() {
let user1 = User {
active: true,
username: String::from("alice"),
email: String::from("alice@example.com"),
sign_in_count: 1,
};
println!("ユーザー名: {}", user1.username);
}rustフィールド名とスコープ内の変数名が一致する場合、フィールド初期化の略記法が使えます。
fn build_user(email: String, username: String) -> User {
User {
active: true,
username,
email,
sign_in_count: 1,
}
}rust構造体更新構文#
.. 構文を使用すると、既存のインスタンスの値を利用して新しいインスタンスを作成できます。
let user2 = User {
email: String::from("bob@example.com"),
..user1
};rust移動(Move)セマンティクスを持つフィールド(user1 の username など)は user2 へ移動する点に注意してください。
タプル構造体とユニット構造体#
タプル構造体はフィールド名を持たず、インデックス位置でアクセスします。
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);rustユニット構造体はフィールドを一切持たず、状態を持たずにトレイトを実装する場合などに役立ちます。
struct AlwaysEqual;
let subject = AlwaysEqual;rustメソッドとimplブロック#
impl ブロック内に構造体のメソッドを定義します。最初の引数は通常 &self(借用)、&mut self(変更)、または self(所有権取得)です。
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
// 関連関数(コンストラクタ)
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("面積: {}", rect1.area());
let sq = Rectangle::square(20);
println!("正方形を包含できるか? {}", rect1.can_hold(&sq));
}rustまとめ#
構造体によりフィールド名やタプル位置を持つ独自型を定義し、impl ブロックでデータに関連する振る舞いを整理できます。シリーズの次回テーマは「列挙型とパターンマッチング」です。