Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
struct の更新構文 / ネスト
Rustの構造体には、既存インスタンスから一部を変えて新しいインスタンスを生成する「構造体更新構文」と、構造体をネストして複雑なデータを表現する機能があります。
構文
// 構造体の更新構文: 残りのフィールドを既存インスタンスからコピーします。
struct Config {
debug: bool,
timeout: u32,
max_connections: u32,
}
let default_cfg = Config { debug: false, timeout: 30, max_connections: 100 };
// debug だけ変えて新しいConfigを作ります。
let dev_cfg = Config {
debug: true,
..default_cfg // 残りは default_cfg からコピーします。
};
// ネストした構造体の例です。
struct Address {
city: String,
country: String,
}
struct Person {
name: String,
age: u32,
address: Address, // 構造体をネストします。
}
概念一覧
| 構文・概念 | 概要 |
|---|---|
| Struct { field: val, ..other } | 一部のフィールドを指定し、残りをotherからコピーした新しいインスタンスを生成します。 |
| ネストした構造体 | struct のフィールドに別の struct を持たせます。 |
| s.inner.field | ネストしたフィールドへのアクセスは . を連鎖させます。 |
| Default::default() | #[derive(Default)]があればデフォルト値で生成します。更新構文と組み合わせて使えます。 |
| struct の分割代入 | let Struct { field1, field2, .. } = s; でフィールドを取り出せます。 |
| match でのパターンマッチ | match s { Struct { field1: x, .. } => ... } で特定フィールドだけマッチします。 |
サンプルコード
#[derive(Debug, Clone, Default)]
struct ServerConfig {
host: String,
port: u16,
max_connections: u32,
timeout_secs: u64,
debug_mode: bool,
}
#[derive(Debug)]
struct Rgb {
r: u8,
g: u8,
b: u8,
}
#[derive(Debug)]
struct Theme {
name: String,
primary: Rgb,
secondary: Rgb,
background: Rgb,
}
fn main() {
// 構造体更新構文で設定を派生させます。
let prod = ServerConfig {
host: String::from("prod.example.com"),
port: 443,
max_connections: 1000,
timeout_secs: 30,
debug_mode: false,
};
// debug_modeだけ変えた開発用設定を作ります。
let dev = ServerConfig {
host: String::from("localhost"),
port: 8080,
debug_mode: true,
..prod.clone() // 残りのフィールドはprodからコピーします。
};
println!("dev: {:?}", dev);
// Default と更新構文の組み合わせです。
let minimal = ServerConfig {
host: String::from("localhost"),
port: 3000,
..Default::default() // 残りはデフォルト値(数値は0、boolはfalse)を使います。
};
println!("minimal: {:?}", minimal);
// ネストした構造体のアクセスです。
let theme = Theme {
name: String::from("Ocean"),
primary: Rgb { r: 0, g: 120, b: 200 },
secondary: Rgb { r: 0, g: 80, b: 150 },
background: Rgb { r: 240, g: 248, b: 255 },
};
println!("テーマ名: {}", theme.name);
println!("メインカラー R: {}", theme.primary.r);
println!("背景 RGB: ({}, {}, {})",
theme.background.r, theme.background.g, theme.background.b);
// 構造体の分割代入です。
let Rgb { r, g, b } = theme.primary;
println!("分割代入: r={}, g={}, b={}", r, g, b);
// match でのパターンマッチです(一部フィールドだけマッチ)。
let config = ServerConfig {
host: String::from("api.example.com"),
port: 443,
..Default::default()
};
match config {
ServerConfig { port: 443, debug_mode: false, .. } => {
println!("本番 HTTPS サーバーです");
}
ServerConfig { debug_mode: true, .. } => {
println!("デバッグモードです");
}
_ => println!("その他の設定です"),
}
}
概要
構造体更新構文(『..other』)でコピーされるフィールドは、Copy型なら問題なくコピーされますが、String型などのヒープデータは所有権が移動します。所有権を保ちたい場合は事前に『clone()』してください。
『Default::default()』との組み合わせは、設定系の構造体でよく使われるパターンです。多くのフィールドにデフォルト値があり、一部だけカスタマイズしたい場合に便利です。
自動トレイト実装は『#[derive(Debug, Clone, PartialEq)]』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。