メソッドチェーン
CoddyのRustジャーニー「Object Oriented Programming」セクションの一部 — レッスン 6/61。
これまで、ミュータブルなメソッドは構造体を変更し、何も返しませんでした。しかし、同じインスタンスに対して複数のメソッドを連続して呼び出したい場合はどうすればよいでしょうか?self への参照を返すことで、メソッドチェーンが可能になります。これは、複数のメソッド呼び出しを1つの式の中で繋げて記述するパターンです。
重要なのは、&mut self メソッドが &mut Self を返すようにすることです:
struct Config {
debug: bool,
timeout: u32,
}
impl Config {
fn new() -> Config {
Config { debug: false, timeout: 30 }
}
fn set_debug(&mut self, value: bool) -> &mut Self {
self.debug = value;
self
}
fn set_timeout(&mut self, seconds: u32) -> &mut Self {
self.timeout = seconds;
self
}
}
各メソッドは構造体を変更し、その後 self(同じインスタンスへの可変参照)を返します。これにより、次のメソッド呼び出しでそのインスタンスに対してすぐに作業を継続できるようになります:
fn main() {
let mut config = Config::new();
config.set_debug(true).set_timeout(60);
println!("Debug: {}, Timeout: {}", config.debug, config.timeout);
// 出力: Debug: true, Timeout: 60
}
3つの個別のステートメントを記述する代わりに、すべてを1つの流れるような行で構成します。この「ビルダースタイル」パターンは、多くのオプション設定を持つオブジェクトをセットアップする際に特に有用で、コードをより簡潔で読みやすくします。
チャレンジ
簡単3つのフィールド、bold (bool)、italic (bool)、および size (u32) を持つ TextStyle 構造体を作成してください。
TextStyle に以下の内容を含む実装ブロックを追加してください:
new—boldをfalse、italicをfalse、sizeを12に設定したTextStyleを返す関連関数set_bold—&mut selfとbool値を受け取り、bold フィールドを設定し、メソッドチェーンのために&mut Selfを返すメソッドset_italic—&mut selfとbool値を受け取り、italic フィールドを設定し、メソッドチェーンのために&mut Selfを返すメソッドset_size—&mut selfとu32値を受け取り、size フィールドを設定し、メソッドチェーンのために&mut Selfを返すメソッド
3つの入力を受け取ります:
- 1行目:bold の設定 (
trueまたはfalse) - 2行目:italic の設定 (
trueまたはfalse) - 3行目:フォントサイズ (u32)
new を使用して可変の TextStyle を作成し、メソッドチェーンを使用して1つの式ですべての3つの設定を適用してください。最終的な状態を以下の形式で出力してください。
期待される出力形式:
Bold: {bold}, Italic: {italic}, Size: {size}チートシート
&mut self を受け取るメソッドは、メソッドチェーンを可能にするために &mut Self を返すことができます:
impl Config {
fn set_debug(&mut self, value: bool) -> &mut Self {
self.debug = value;
self
}
fn set_timeout(&mut self, seconds: u32) -> &mut Self {
self.timeout = seconds;
self
}
}
これにより、単一の式で複数のメソッド呼び出しが可能になります:
let mut config = Config::new();
config.set_debug(true).set_timeout(60);
各メソッドは構造体を変更し、同じインスタンスへの可変の参照を返します。これにより、次のメソッドがすぐにそのインスタンスに対して操作を継続できるようになります。
自分で試してみよう
use std::io;
// TODO: ここで TextStyle 構造体を定義します
// TODO: TextStyle の実装ブロックを追加します。以下の内容を含めてください:
// - new() 関連関数
// - set_bold() メソッド
// - set_italic() メソッド
// - set_size() メソッド
fn main() {
let mut input = String::new();
// 太字設定を読み込む
io::stdin().read_line(&mut input).expect("Failed to read line");
let bold: bool = input.trim().parse().expect("Invalid bool");
input.clear();
// 斜体設定を読み込む
io::stdin().read_line(&mut input).expect("Failed to read line");
let italic: bool = input.trim().parse().expect("Invalid bool");
input.clear();
// サイズ設定を読み込む
io::stdin().read_line(&mut input).expect("Failed to read line");
let size: u32 = input.trim().parse().expect("Invalid u32");
// TODO: new() を使用して可変の TextStyle を作成し、メソッドチェーンを使用して
// 3つの設定すべてを単一の式で適用します
// TODO: 次の形式で結果を出力します: Bold: {bold}, Italic: {italic}, Size: {size}
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。